NodeGoat scann report
| Risk Level | Number of Alerts |
|---|---|
|
High
|
2
|
|
Medium
|
5
|
|
Low
|
5
|
|
Informational
|
7
|
|
False Positives:
|
0
|
| Name | Risk Level | Number of Instances |
|---|---|---|
| Cross Site Scripting (DOM Based) | High | 4 |
| Cross Site Scripting (Reflected) | High | 3 |
| CSP: Wildcard Directive | Medium | 5 |
| Content Security Policy (CSP) Header Not Set | Medium | 6 |
| Directory Browsing | Medium | 1 |
| Missing Anti-clickjacking Header | Medium | 6 |
| Vulnerable JS Library | Medium | 2 |
| Cookie without SameSite Attribute | Low | 7 |
| Cross-Domain JavaScript Source File Inclusion | Low | 6 |
| Server Leaks Information via "X-Powered-By" HTTP Response Header Field(s) | Low | 16 |
| Timestamp Disclosure - Unix | Low | 1 |
| X-Content-Type-Options Header Missing | Low | 10 |
| Authentication Request Identified | Informational | 5 |
| Information Disclosure - Suspicious Comments | Informational | 3 |
| Loosely Scoped Cookie | Informational | 23 |
| Modern Web Application | Informational | 4 |
| Session Management Response Identified | Informational | 7 |
| User Agent Fuzzer | Informational | 32 |
| User Controllable HTML Element Attribute (Potential XSS) | Informational | 7 |
| HTTP Response Code | Number of Responses |
|---|---|
| 304 Not Modified |
3481
|
| 404 Not Found |
523
|
| 405 Method Not Allowed |
3
|
| 200 OK |
6582
|
| 301 Moved Permanently |
287
|
| 400 Bad Request |
2
|
| 302 Found |
184
|
| Authentication Statistics | Number of Responses |
|---|---|
|
!reports.report.stats.auth.sessiontoken.connect.sid!
|
33
|
| Parameter Name | Type | Flags | Times Used | # Values |
|---|---|---|---|---|
|
connect.sid
|
Cookie
|
Path=/
HttpOnly
|
4245
|
23
|
|
_csrf
|
Form
|
anticsrf
|
271
|
1
|
|
email
|
Form
|
148
|
1
|
|
|
firstName
|
Form
|
148
|
14
|
|
|
lastName
|
Form
|
148
|
14
|
|
|
password
|
Form
|
271
|
1
|
|
|
userName
|
Form
|
271
|
30
|
|
|
verify
|
Form
|
148
|
1
|
|
|
v
|
URL
|
32
|
1
|
|
|
Accept-Ranges
|
Header
|
3427
|
1
|
|
|
Cache-Control
|
Header
|
3443
|
2
|
|
|
Connection
|
Header
|
4245
|
1
|
|
|
Content-Length
|
Header
|
764
|
28
|
|
|
Content-Security-Policy
|
Header
|
5
|
1
|
|
|
Content-Type
|
Header
|
764
|
7
|
|
|
Date
|
Header
|
4245
|
179
|
|
|
ETag
|
Header
|
4060
|
41
|
|
|
Keep-Alive
|
Header
|
4245
|
1
|
|
|
Last-Modified
|
Header
|
3427
|
1
|
|
|
Location
|
Header
|
180
|
1
|
|
|
Vary
|
Header
|
180
|
1
|
|
|
X-Content-Type-Options
|
Header
|
5
|
1
|
|
|
X-Powered-By
|
Header
|
4245
|
1
|
|
High |
Cross Site Scripting (DOM Based) |
|---|---|
| Description |
Cross-site Scripting (XSS) is an attack technique that involves echoing attacker-supplied code into a user's browser instance. A browser instance can be a standard web browser client, or a browser object embedded in a software product such as the browser within WinAmp, an RSS reader, or an email client. The code itself is usually written in HTML/JavaScript, but may also extend to VBScript, ActiveX, Java, Flash, or any other browser-supported technology.
When an attacker gets a user's browser to execute his/her code, the code will run within the security context (or zone) of the hosting web site. With this level of privilege, the code has the ability to read, modify and transmit any sensitive data accessible by the browser. A Cross-site Scripted user could have his/her account hijacked (cookie theft), their browser redirected to another location, or possibly shown fraudulent content delivered by the web site they are visiting. Cross-site Scripting attacks essentially compromise the trust relationship between a user and the web site. Applications utilizing browser object instances which load content from the file system may execute code under the local machine zone allowing for system compromise.
There are three types of Cross-site Scripting attacks: non-persistent, persistent and DOM-based.
Non-persistent attacks and DOM-based attacks require a user to either visit a specially crafted link laced with malicious code, or visit a malicious web page containing a web form, which when posted to the vulnerable site, will mount the attack. Using a malicious form will oftentimes take place when the vulnerable resource only accepts HTTP POST requests. In such a case, the form can be submitted automatically, without the victim's knowledge (e.g. by using JavaScript). Upon clicking on the malicious link or submitting the malicious form, the XSS payload will get echoed back and will get interpreted by the user's browser and execute. Another technique to send almost arbitrary requests (GET and POST) is by using an embedded client, such as Adobe Flash.
Persistent attacks occur when the malicious code is submitted to a web site where it's stored for a period of time. Examples of an attacker's favorite targets often include message board posts, web mail messages, and web chat software. The unsuspecting user is not required to interact with any additional site/link (e.g. an attacker site or a malicious link sent via email), just simply view the web page containing the code.
|
| URL | http://jenkins_docker-compose_application_web_1:4000/login#jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert(5397) )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert(5397)//>\x3e |
| Method | GET |
| Parameter | |
| Attack | #jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert(5397) )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert(5397)//>\x3e |
| Evidence | |
| Request Header - size: 500 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/login HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive Cookie: connect.sid=s%3AMVRt5PPOLZFLrXwgGcIVuLcIrAUh1wsa.dphg%2BJZQll%2BReytakGCaiv9Mr4yficPo5orWBILg83E Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 14 bytes. |
HTTP/1.0 0
|
| Response Body - size: 0 bytes. |
|
| URL | http://jenkins_docker-compose_application_web_1:4000/login#javascript:alert(5397) |
| Method | GET |
| Parameter | |
| Attack | #javascript:alert(5397) |
| Evidence | |
| Request Header - size: 500 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/login HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive Cookie: connect.sid=s%3AMVRt5PPOLZFLrXwgGcIVuLcIrAUh1wsa.dphg%2BJZQll%2BReytakGCaiv9Mr4yficPo5orWBILg83E Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 14 bytes. |
HTTP/1.0 0
|
| Response Body - size: 0 bytes. |
|
| URL | http://jenkins_docker-compose_application_web_1:4000/login#jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert(5397) )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert(5397)//>\x3e |
| Method | POST |
| Parameter | |
| Attack | #jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert(5397) )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert(5397)//>\x3e |
| Evidence | |
| Request Header - size: 701 bytes. |
POST http://jenkins_docker-compose_application_web_1:4000/login HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Content-Type: application/x-www-form-urlencoded Content-Length: 50 Origin: http://jenkins_docker-compose_application_web_1:4000 Connection: keep-alive Cookie: connect.sid=s%3AMVRt5PPOLZFLrXwgGcIVuLcIrAUh1wsa.dphg%2BJZQll%2BReytakGCaiv9Mr4yficPo5orWBILg83E Upgrade-Insecure-Requests: 1 |
| Request Body - size: 50 bytes. |
userName=NKyAaNFzVybQGadhZiMejEYu&password=&_csrf=
|
| Response Header - size: 14 bytes. |
HTTP/1.0 0
|
| Response Body - size: 0 bytes. |
|
| URL | http://jenkins_docker-compose_application_web_1:4000/login#javascript:alert(5397) |
| Method | POST |
| Parameter | |
| Attack | #javascript:alert(5397) |
| Evidence | |
| Request Header - size: 701 bytes. |
POST http://jenkins_docker-compose_application_web_1:4000/login HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Content-Type: application/x-www-form-urlencoded Content-Length: 50 Origin: http://jenkins_docker-compose_application_web_1:4000 Connection: keep-alive Cookie: connect.sid=s%3AMVRt5PPOLZFLrXwgGcIVuLcIrAUh1wsa.dphg%2BJZQll%2BReytakGCaiv9Mr4yficPo5orWBILg83E Upgrade-Insecure-Requests: 1 |
| Request Body - size: 50 bytes. |
userName=NKyAaNFzVybQGadhZiMejEYu&password=&_csrf=
|
| Response Header - size: 14 bytes. |
HTTP/1.0 0
|
| Response Body - size: 0 bytes. |
|
| Instances | 4 |
| Solution |
Phase: Architecture and Design
Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.
Examples of libraries and frameworks that make it easier to generate properly encoded output include Microsoft's Anti-XSS library, the OWASP ESAPI Encoding module, and Apache Wicket.
Phases: Implementation; Architecture and Design
Understand the context in which your data will be used and the encoding that will be expected. This is especially important when transmitting data between different components, or when generating outputs that can contain multiple encodings at the same time, such as web pages or multi-part mail messages. Study all expected communication protocols and data representations to determine the required encoding strategies.
For any data that will be output to another web page, especially any data that was received from external inputs, use the appropriate encoding on all non-alphanumeric characters.
Consult the XSS Prevention Cheat Sheet for more details on the types of encoding and escaping that are needed.
Phase: Architecture and Design
For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. Attackers can bypass the client-side checks by modifying values after the checks have been performed, or by changing the client to remove the client-side checks entirely. Then, these modified values would be submitted to the server.
If available, use structured mechanisms that automatically enforce the separation between data and code. These mechanisms may be able to provide the relevant quoting, encoding, and validation automatically, instead of relying on the developer to provide this capability at every point where output is generated.
Phase: Implementation
For every web page that is generated, use and specify a character encoding such as ISO-8859-1 or UTF-8. When an encoding is not specified, the web browser may choose a different encoding by guessing which encoding is actually being used by the web page. This can cause the web browser to treat certain sequences as special, opening up the client to subtle XSS attacks. See CWE-116 for more mitigations related to encoding/escaping.
To help mitigate XSS attacks against the user's session cookie, set the session cookie to be HttpOnly. In browsers that support the HttpOnly feature (such as more recent versions of Internet Explorer and Firefox), this attribute can prevent the user's session cookie from being accessible to malicious client-side scripts that use document.cookie. This is not a complete solution, since HttpOnly is not supported by all browsers. More importantly, XMLHTTPRequest and other powerful browser technologies provide read access to HTTP headers, including the Set-Cookie header in which the HttpOnly flag is set.
Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use an allow list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does. Do not rely exclusively on looking for malicious or malformed inputs (i.e., do not rely on a deny list). However, deny lists can be useful for detecting potential attacks or determining which inputs are so malformed that they should be rejected outright.
When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid because it only contains alphanumeric characters, but it is not valid if you are expecting colors such as "red" or "blue."
Ensure that you perform input validation at well-defined interfaces within the application. This will help protect the application even if a component is reused or moved elsewhere.
|
| Reference |
http://projects.webappsec.org/Cross-Site-Scripting
https://cwe.mitre.org/data/definitions/79.html |
| Tags |
WSTG-v42-CLNT-01
OWASP_2021_A03 OWASP_2017_A07 |
| CWE Id | 79 |
| WASC Id | 8 |
| Plugin Id | 40026 |
|
High |
Cross Site Scripting (Reflected) |
|---|---|
| Description |
Cross-site Scripting (XSS) is an attack technique that involves echoing attacker-supplied code into a user's browser instance. A browser instance can be a standard web browser client, or a browser object embedded in a software product such as the browser within WinAmp, an RSS reader, or an email client. The code itself is usually written in HTML/JavaScript, but may also extend to VBScript, ActiveX, Java, Flash, or any other browser-supported technology.
When an attacker gets a user's browser to execute his/her code, the code will run within the security context (or zone) of the hosting web site. With this level of privilege, the code has the ability to read, modify and transmit any sensitive data accessible by the browser. A Cross-site Scripted user could have his/her account hijacked (cookie theft), their browser redirected to another location, or possibly shown fraudulent content delivered by the web site they are visiting. Cross-site Scripting attacks essentially compromise the trust relationship between a user and the web site. Applications utilizing browser object instances which load content from the file system may execute code under the local machine zone allowing for system compromise.
There are three types of Cross-site Scripting attacks: non-persistent, persistent and DOM-based.
Non-persistent attacks and DOM-based attacks require a user to either visit a specially crafted link laced with malicious code, or visit a malicious web page containing a web form, which when posted to the vulnerable site, will mount the attack. Using a malicious form will oftentimes take place when the vulnerable resource only accepts HTTP POST requests. In such a case, the form can be submitted automatically, without the victim's knowledge (e.g. by using JavaScript). Upon clicking on the malicious link or submitting the malicious form, the XSS payload will get echoed back and will get interpreted by the user's browser and execute. Another technique to send almost arbitrary requests (GET and POST) is by using an embedded client, such as Adobe Flash.
Persistent attacks occur when the malicious code is submitted to a web site where it's stored for a period of time. Examples of an attacker's favorite targets often include message board posts, web mail messages, and web chat software. The unsuspecting user is not required to interact with any additional site/link (e.g. an attacker site or a malicious link sent via email), just simply view the web page containing the code.
|
| URL | http://jenkins_docker-compose_application_web_1:4000/login |
| Method | POST |
| Parameter | userName |
| Attack | "><scrIpt>alert(1);</scRipt> |
| Evidence | "><scrIpt>alert(1);</scRipt> |
| Request Header - size: 701 bytes. |
POST http://jenkins_docker-compose_application_web_1:4000/login HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Content-Type: application/x-www-form-urlencoded content-length: 74 Origin: http://jenkins_docker-compose_application_web_1:4000 Connection: keep-alive Cookie: connect.sid=s%3AMVRt5PPOLZFLrXwgGcIVuLcIrAUh1wsa.dphg%2BJZQll%2BReytakGCaiv9Mr4yficPo5orWBILg83E Upgrade-Insecure-Requests: 1 |
| Request Body - size: 74 bytes. |
userName=%22%3E%3CscrIpt%3Ealert%281%29%3B%3C%2FscRipt%3E&password=&_csrf=
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 7534 ETag: W/"1d6e-2hjNSXfSY+ClZxwkxHlzkgAxe2s" Date: Mon, 29 Jan 2024 16:36:48 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 7,534 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="OWASP NodeGoat Project: Insecure App"> <meta name="version" content="v1.2"> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="https://www.owasp.org/index.php/Projects/OWASP_Node_js_Goat_Project">OWASP Node Goat Project</a> </div> <!-- Nav Links--> <div class="collapse navbar-collapse navbar-ex1-collapse"> <!-- top nav --> <ul class="nav navbar-nav navbar-right navbar-user"> <li class="dropdown user-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" style="font-size: larger"><i class="fa fa-info-circle"></i></a> <ul class="dropdown-menu alert-dropdown" style="min-width: 350px; padding: 10px"> <li> <p> The OWASP Node Goat is an educational Node.js web application vulnerable to the <a target="_blank" href="https://www.owasp.org/index.php/Top_10_2013-Top_10"> OWASP Top 10</a> risks.</p> <p>It is intended to show how each of these vulnerabilities can manifest in a Node.js specific way, and provides the subsequent mitigation for each with source code examples. </p> <p>To start hacking the application, login using the form below, or access the tutorial guide to know more.</p> </li> <li class="divider"></li> <li style="text-align: right"> <i class="fa fa-tag"> </i> v1.2 </li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div style="text-align: center; padding: 30px"> <img src="/images/owasplogo.png" height="80px"> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-4"></div> <div class="col-lg-4"> <div class="panel panel-info"> <div class="panel-heading" style="text-align: center"> <a href="/tutorial" target="_blank"> <b><span class="fa fa-book"></span> Tutorial Guide:</b> Learn OWASP Top 10 </a> </div> </div> <div class="panel panel-default"> <div class="panel-heading" style="text-align: center"> <span style="font-size: x-large"> <span class="fa fa-bullseye"></span>Retire<b>Easy</b> </span> <br /> <span style="font-size: medium">Employee Retirement Savings Management</span> <br /> <br /> </div> <div class="panel-body"> <div class="alert alert-dismissable alert-danger"> <button type="button" class="close" data-dismiss="alert">×</button> Invalid username </div> <form method="post" role="form" method="post" id="loginform"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" name="userName" value=""><scrIpt>alert(1);</scRipt>" placeholder="Enter User Name"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter Password"> </div> <input type="hidden" name="_csrf" value="" /> <div class="row"> <div class="col-lg-4"><a href="/signup">New user? Sign Up</a> </div> <div class="col-lg-5"></div> <div class="col-lg-3"> <button type="submit" class="btn btn-danger">Submit</button> </div> </div> </form> </div> </div> </div> <div class="col-lg-4"></div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> <!-- /.row --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> <script type="application/javascript"> const areCookiesEnabled = () => { const cookieEnabled = navigator.cookieEnabled; // When cookieEnabled flag is present and false then cookies are disabled. if (!cookieEnabled) return false; // try to set a test cookie if we can't see any cookies and we're using // either a browser that doesn't support navigator.cookieEnabled // or IE (which always returns true for navigator.cookieEnabled) if (!document.cookie && cookieEnabled === null) { document.cookie = "testcookie=1"; if (!document.cookie) return false; document.cookie = "testcookie=; expires=" + new Date(0).toUTCString(); } return true; } $(document).ready(() => { if (!areCookiesEnabled()) { $("#page-wrapper").prepend("<div class=\"row\"><div class=\"col-lg-12\"><div class=\"alert alert-danger\">Cookies are not enabled on your browser. Please enable cookies in your browser preferences to continue.</div></div></div>"); } }); </script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/signup |
| Method | POST |
| Parameter | |
| Attack | "><scrIpt>alert(1);</scRipt> |
| Evidence | "><scrIpt>alert(1);</scRipt> |
| Request Header - size: 704 bytes. |
POST http://jenkins_docker-compose_application_web_1:4000/signup HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/signup Content-Type: application/x-www-form-urlencoded content-length: 158 Origin: http://jenkins_docker-compose_application_web_1:4000 Connection: keep-alive Cookie: connect.sid=s%3A6l4x9lvFSBO3eZCtcIaSh1m9xH73hlif.%2FKVneLbM19x9O8l4PH%2BJdUKdkH3mt5ZwclTb52i24zk Upgrade-Insecure-Requests: 1 |
| Request Body - size: 158 bytes. |
userName=ECeNuwflHrjiWkuqLKvwCJPTIdltAxlY&firstName=FCMTdCda&lastName=raNnIAru&password=&verify=&email=%22%3E%3CscrIpt%3Ealert%281%29%3B%3C%2FscRipt%3E&_csrf=
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 4982 ETag: W/"1376-q1coHV6k/0gcGGn0LyV9XyJx9SE" Date: Mon, 29 Jan 2024 16:36:49 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 4,982 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <!-- Add custom CSS here --> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="/">OWASP Node Goat Project</a> </div> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div class="well well-sm"> Already a user? <a href="/login">Login</a> <p> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="alert alert-dismissable alert-danger"> <button type="button" class="close" data-dismiss="alert">×</button> <p>Invalid user name.</p> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Enter sign up information</h3> </div> <div class="panel-body"> <form method="post" role="form" method="post"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" value="ECeNuwflHrjiWkuqLKvwCJPTIdltAxlY" name="userName" placeholder="Enter user name"> </div> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" value="" name="firstName" placeholder="Enter first name"> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" value="" name="lastName" placeholder="Enter last name"> </div> <div class="form-group"> <label for="lastname">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Verify Password</label> <input type="password" class="form-control" id="verify" name="verify" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Email (Optional)</label> <input type="email" class="form-control" id="email" name="email" value=""><scrIpt>alert(1);</scRipt>" placeholder="Enter email"> </div> <input type="hidden" name="_csrf" value=""></input> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/signup |
| Method | POST |
| Parameter | userName |
| Attack | "><scrIpt>alert(1);</scRipt> |
| Evidence | "><scrIpt>alert(1);</scRipt> |
| Request Header - size: 704 bytes. |
POST http://jenkins_docker-compose_application_web_1:4000/signup HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/signup Content-Type: application/x-www-form-urlencoded content-length: 126 Origin: http://jenkins_docker-compose_application_web_1:4000 Connection: keep-alive Cookie: connect.sid=s%3A6l4x9lvFSBO3eZCtcIaSh1m9xH73hlif.%2FKVneLbM19x9O8l4PH%2BJdUKdkH3mt5ZwclTb52i24zk Upgrade-Insecure-Requests: 1 |
| Request Body - size: 126 bytes. |
userName=%22%3E%3CscrIpt%3Ealert%281%29%3B%3C%2FscRipt%3E&firstName=FCMTdCda&lastName=raNnIAru&password=&verify=&email=&_csrf=
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 4950 ETag: W/"1356-LcWhx6MzICL9F9gIioOKAt03AzI" Date: Mon, 29 Jan 2024 16:36:48 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 4,950 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <!-- Add custom CSS here --> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="/">OWASP Node Goat Project</a> </div> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div class="well well-sm"> Already a user? <a href="/login">Login</a> <p> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="alert alert-dismissable alert-danger"> <button type="button" class="close" data-dismiss="alert">×</button> <p>Invalid user name.</p> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Enter sign up information</h3> </div> <div class="panel-body"> <form method="post" role="form" method="post"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" value=""><scrIpt>alert(1);</scRipt>" name="userName" placeholder="Enter user name"> </div> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" value="" name="firstName" placeholder="Enter first name"> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" value="" name="lastName" placeholder="Enter last name"> </div> <div class="form-group"> <label for="lastname">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Verify Password</label> <input type="password" class="form-control" id="verify" name="verify" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Email (Optional)</label> <input type="email" class="form-control" id="email" name="email" value="" placeholder="Enter email"> </div> <input type="hidden" name="_csrf" value=""></input> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| Instances | 3 |
| Solution |
Phase: Architecture and Design
Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.
Examples of libraries and frameworks that make it easier to generate properly encoded output include Microsoft's Anti-XSS library, the OWASP ESAPI Encoding module, and Apache Wicket.
Phases: Implementation; Architecture and Design
Understand the context in which your data will be used and the encoding that will be expected. This is especially important when transmitting data between different components, or when generating outputs that can contain multiple encodings at the same time, such as web pages or multi-part mail messages. Study all expected communication protocols and data representations to determine the required encoding strategies.
For any data that will be output to another web page, especially any data that was received from external inputs, use the appropriate encoding on all non-alphanumeric characters.
Consult the XSS Prevention Cheat Sheet for more details on the types of encoding and escaping that are needed.
Phase: Architecture and Design
For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. Attackers can bypass the client-side checks by modifying values after the checks have been performed, or by changing the client to remove the client-side checks entirely. Then, these modified values would be submitted to the server.
If available, use structured mechanisms that automatically enforce the separation between data and code. These mechanisms may be able to provide the relevant quoting, encoding, and validation automatically, instead of relying on the developer to provide this capability at every point where output is generated.
Phase: Implementation
For every web page that is generated, use and specify a character encoding such as ISO-8859-1 or UTF-8. When an encoding is not specified, the web browser may choose a different encoding by guessing which encoding is actually being used by the web page. This can cause the web browser to treat certain sequences as special, opening up the client to subtle XSS attacks. See CWE-116 for more mitigations related to encoding/escaping.
To help mitigate XSS attacks against the user's session cookie, set the session cookie to be HttpOnly. In browsers that support the HttpOnly feature (such as more recent versions of Internet Explorer and Firefox), this attribute can prevent the user's session cookie from being accessible to malicious client-side scripts that use document.cookie. This is not a complete solution, since HttpOnly is not supported by all browsers. More importantly, XMLHTTPRequest and other powerful browser technologies provide read access to HTTP headers, including the Set-Cookie header in which the HttpOnly flag is set.
Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use an allow list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does. Do not rely exclusively on looking for malicious or malformed inputs (i.e., do not rely on a deny list). However, deny lists can be useful for detecting potential attacks or determining which inputs are so malformed that they should be rejected outright.
When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid because it only contains alphanumeric characters, but it is not valid if you are expecting colors such as "red" or "blue."
Ensure that you perform input validation at well-defined interfaces within the application. This will help protect the application even if a component is reused or moved elsewhere.
|
| Reference |
http://projects.webappsec.org/Cross-Site-Scripting
https://cwe.mitre.org/data/definitions/79.html |
| Tags |
OWASP_2021_A03
WSTG-v42-INPV-01 OWASP_2017_A07 |
| CWE Id | 79 |
| WASC Id | 8 |
| Plugin Id | 40012 |
|
Medium |
CSP: Wildcard Directive |
|---|---|
| Description |
Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks. Including (but not limited to) Cross Site Scripting (XSS), and data injection attacks. These attacks are used for everything from data theft to site defacement or distribution of malware. CSP provides a set of standard HTTP headers that allow website owners to declare approved sources of content that browsers should be allowed to load on that page — covered types are JavaScript, CSS, HTML frames, fonts, images and embeddable objects such as Java applets, ActiveX, audio and video files.
|
| URL | http://jenkins_docker-compose_application_web_1:4000/.git/index |
| Method | GET |
| Parameter | Content-Security-Policy |
| Attack | |
| Evidence | default-src 'self' |
| Request Header - size: 190 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/.git/index HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 149 set-cookie: connect.sid=s%3AwqnsNnm0JNFr_c-ILLR7CjdG_uYo4VVW.cytWnLVcvPGOUZGePLI29wnKDcy1OW5%2B892M9AdtZFA; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 149 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /.git/index</pre> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/.svn/entries |
| Method | GET |
| Parameter | Content-Security-Policy |
| Attack | |
| Evidence | default-src 'self' |
| Request Header - size: 192 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/.svn/entries HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 151 set-cookie: connect.sid=s%3AjqDNMm6bCo9hIi4k-zSL1pEgKROsV3T2.QSVBq3yrtKUDHQC9%2FBsCW1JAc24P7RopxS7EnSiFTqA; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 151 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /.svn/entries</pre> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/.svn/wc.db |
| Method | GET |
| Parameter | Content-Security-Policy |
| Attack | |
| Evidence | default-src 'self' |
| Request Header - size: 190 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/.svn/wc.db HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 149 set-cookie: connect.sid=s%3Asv3hkzV3_ZpgbbMGSiyiA7G3ZgnCwyMt.hhEWpjJazSBDCxwMLxvQhhRLtPw%2Fsa2BSVPotWkO4KU; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 149 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /.svn/wc.db</pre> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/robots.txt |
| Method | GET |
| Parameter | Content-Security-Policy |
| Attack | |
| Evidence | default-src 'self' |
| Request Header - size: 190 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/robots.txt HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 149 set-cookie: connect.sid=s%3Ar4tgfCP6lvWxc8TFxe_odDtmgrPbmY4o.uLijHm0LWLpf9J92CTUdxM7UMbXX2Nvq6KJK%2FqEzGeQ; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 149 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /robots.txt</pre> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/sitemap.xml |
| Method | GET |
| Parameter | Content-Security-Policy |
| Attack | |
| Evidence | default-src 'self' |
| Request Header - size: 191 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/sitemap.xml HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 150 set-cookie: connect.sid=s%3A5evrs8D1vchX94X4CB-rok2Y6wuJEGXy.MB31%2BtYmIy1LskkHviWKPS7nQdX9n4DogB2v0z1lNIM; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 150 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /sitemap.xml</pre> </body> </html> |
| Instances | 5 |
| Solution |
Ensure that your web server, application server, load balancer, etc. is properly configured to set the Content-Security-Policy header.
|
| Reference |
http://www.w3.org/TR/CSP2/
http://www.w3.org/TR/CSP/ http://caniuse.com/#search=content+security+policy http://content-security-policy.com/ https://github.com/shapesecurity/salvation https://developers.google.com/web/fundamentals/security/csp#policy_applies_to_a_wide_variety_of_resources |
| Tags |
OWASP_2021_A05
OWASP_2017_A06 |
| CWE Id | 693 |
| WASC Id | 15 |
| Plugin Id | 10055 |
|
Medium |
Content Security Policy (CSP) Header Not Set |
|---|---|
| Description |
Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement or distribution of malware. CSP provides a set of standard HTTP headers that allow website owners to declare approved sources of content that browsers should be allowed to load on that page — covered types are JavaScript, CSS, HTML frames, fonts, images and embeddable objects such as Java applets, ActiveX, audio and video files.
|
| URL | http://jenkins_docker-compose_application_web_1:4000 |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | |
| Request Header - size: 290 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000 HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 360 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 7208 ETag: W/"1c28-jzMKoc+DPSvVfJwC7jYRDNnpaUs" set-cookie: connect.sid=s%3AQwLdXMcnkQaq6YvZvtTYL4BnMHb9eAv4.NEqu3dKtNsc%2F4nMbEdjeASDgie%2Bfj1FBoAOQDFNalTo; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 7,208 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="OWASP NodeGoat Project: Insecure App"> <meta name="version" content="v1.2"> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="https://www.owasp.org/index.php/Projects/OWASP_Node_js_Goat_Project">OWASP Node Goat Project</a> </div> <!-- Nav Links--> <div class="collapse navbar-collapse navbar-ex1-collapse"> <!-- top nav --> <ul class="nav navbar-nav navbar-right navbar-user"> <li class="dropdown user-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" style="font-size: larger"><i class="fa fa-info-circle"></i></a> <ul class="dropdown-menu alert-dropdown" style="min-width: 350px; padding: 10px"> <li> <p> The OWASP Node Goat is an educational Node.js web application vulnerable to the <a target="_blank" href="https://www.owasp.org/index.php/Top_10_2013-Top_10"> OWASP Top 10</a> risks.</p> <p>It is intended to show how each of these vulnerabilities can manifest in a Node.js specific way, and provides the subsequent mitigation for each with source code examples. </p> <p>To start hacking the application, login using the form below, or access the tutorial guide to know more.</p> </li> <li class="divider"></li> <li style="text-align: right"> <i class="fa fa-tag"> </i> v1.2 </li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div style="text-align: center; padding: 30px"> <img src="/images/owasplogo.png" height="80px"> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-4"></div> <div class="col-lg-4"> <div class="panel panel-info"> <div class="panel-heading" style="text-align: center"> <a href="/tutorial" target="_blank"> <b><span class="fa fa-book"></span> Tutorial Guide:</b> Learn OWASP Top 10 </a> </div> </div> <div class="panel panel-default"> <div class="panel-heading" style="text-align: center"> <span style="font-size: x-large"> <span class="fa fa-bullseye"></span>Retire<b>Easy</b> </span> <br /> <span style="font-size: medium">Employee Retirement Savings Management</span> <br /> <br /> </div> <div class="panel-body"> <form method="post" role="form" method="post" id="loginform"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" name="userName" value="" placeholder="Enter User Name"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter Password"> </div> <input type="hidden" name="_csrf" value="" /> <div class="row"> <div class="col-lg-4"><a href="/signup">New user? Sign Up</a> </div> <div class="col-lg-5"></div> <div class="col-lg-3"> <button type="submit" class="btn btn-danger">Submit</button> </div> </div> </form> </div> </div> </div> <div class="col-lg-4"></div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> <!-- /.row --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> <script type="application/javascript"> const areCookiesEnabled = () => { const cookieEnabled = navigator.cookieEnabled; // When cookieEnabled flag is present and false then cookies are disabled. if (!cookieEnabled) return false; // try to set a test cookie if we can't see any cookies and we're using // either a browser that doesn't support navigator.cookieEnabled // or IE (which always returns true for navigator.cookieEnabled) if (!document.cookie && cookieEnabled === null) { document.cookie = "testcookie=1"; if (!document.cookie) return false; document.cookie = "testcookie=; expires=" + new Date(0).toUTCString(); } return true; } $(document).ready(() => { if (!areCookiesEnabled()) { $("#page-wrapper").prepend("<div class=\"row\"><div class=\"col-lg-12\"><div class=\"alert alert-danger\">Cookies are not enabled on your browser. Please enable cookies in your browser preferences to continue.</div></div></div>"); } }); </script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/login |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | |
| Request Header - size: 498 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/login HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 7208 ETag: W/"1c28-jzMKoc+DPSvVfJwC7jYRDNnpaUs" Date: Mon, 29 Jan 2024 16:33:31 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 7,208 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="OWASP NodeGoat Project: Insecure App"> <meta name="version" content="v1.2"> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="https://www.owasp.org/index.php/Projects/OWASP_Node_js_Goat_Project">OWASP Node Goat Project</a> </div> <!-- Nav Links--> <div class="collapse navbar-collapse navbar-ex1-collapse"> <!-- top nav --> <ul class="nav navbar-nav navbar-right navbar-user"> <li class="dropdown user-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" style="font-size: larger"><i class="fa fa-info-circle"></i></a> <ul class="dropdown-menu alert-dropdown" style="min-width: 350px; padding: 10px"> <li> <p> The OWASP Node Goat is an educational Node.js web application vulnerable to the <a target="_blank" href="https://www.owasp.org/index.php/Top_10_2013-Top_10"> OWASP Top 10</a> risks.</p> <p>It is intended to show how each of these vulnerabilities can manifest in a Node.js specific way, and provides the subsequent mitigation for each with source code examples. </p> <p>To start hacking the application, login using the form below, or access the tutorial guide to know more.</p> </li> <li class="divider"></li> <li style="text-align: right"> <i class="fa fa-tag"> </i> v1.2 </li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div style="text-align: center; padding: 30px"> <img src="/images/owasplogo.png" height="80px"> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-4"></div> <div class="col-lg-4"> <div class="panel panel-info"> <div class="panel-heading" style="text-align: center"> <a href="/tutorial" target="_blank"> <b><span class="fa fa-book"></span> Tutorial Guide:</b> Learn OWASP Top 10 </a> </div> </div> <div class="panel panel-default"> <div class="panel-heading" style="text-align: center"> <span style="font-size: x-large"> <span class="fa fa-bullseye"></span>Retire<b>Easy</b> </span> <br /> <span style="font-size: medium">Employee Retirement Savings Management</span> <br /> <br /> </div> <div class="panel-body"> <form method="post" role="form" method="post" id="loginform"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" name="userName" value="" placeholder="Enter User Name"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter Password"> </div> <input type="hidden" name="_csrf" value="" /> <div class="row"> <div class="col-lg-4"><a href="/signup">New user? Sign Up</a> </div> <div class="col-lg-5"></div> <div class="col-lg-3"> <button type="submit" class="btn btn-danger">Submit</button> </div> </div> </form> </div> </div> </div> <div class="col-lg-4"></div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> <!-- /.row --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> <script type="application/javascript"> const areCookiesEnabled = () => { const cookieEnabled = navigator.cookieEnabled; // When cookieEnabled flag is present and false then cookies are disabled. if (!cookieEnabled) return false; // try to set a test cookie if we can't see any cookies and we're using // either a browser that doesn't support navigator.cookieEnabled // or IE (which always returns true for navigator.cookieEnabled) if (!document.cookie && cookieEnabled === null) { document.cookie = "testcookie=1"; if (!document.cookie) return false; document.cookie = "testcookie=; expires=" + new Date(0).toUTCString(); } return true; } $(document).ready(() => { if (!areCookiesEnabled()) { $("#page-wrapper").prepend("<div class=\"row\"><div class=\"col-lg-12\"><div class=\"alert alert-danger\">Cookies are not enabled on your browser. Please enable cookies in your browser preferences to continue.</div></div></div>"); } }); </script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/signup |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | |
| Request Header - size: 570 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/signup HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Connection: keep-alive Cookie: connect.sid=s%3AIF9C8qOuAKIcRfBbQqlCJJXkbklBl-qx.oP%2BOVOd6OEM180NJJ02GnInP0AWbC%2BM6FRljTBVrJ0U Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 4551 ETag: W/"11c7-Y/9Bw9cdVN5/8qERn0VzdrK/7QY" Date: Mon, 29 Jan 2024 16:33:44 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 4,551 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <!-- Add custom CSS here --> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="/">OWASP Node Goat Project</a> </div> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div class="well well-sm"> Already a user? <a href="/login">Login</a> <p> </div> </div> </div> <!-- /.row --> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Enter sign up information</h3> </div> <div class="panel-body"> <form method="post" role="form" method="post"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" value="" name="userName" placeholder="Enter user name"> </div> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" value="" name="firstName" placeholder="Enter first name"> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" value="" name="lastName" placeholder="Enter last name"> </div> <div class="form-group"> <label for="lastname">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Verify Password</label> <input type="password" class="form-control" id="verify" name="verify" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Email (Optional)</label> <input type="email" class="form-control" id="email" name="email" value="" placeholder="Enter email"> </div> <input type="hidden" name="_csrf" value=""></input> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/tutorial |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | |
| Request Header - size: 570 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/tutorial HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 233 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 27010 ETag: W/"6982-Li2JuR00Z8ulcGovuWWgt5WzEqM" Date: Mon, 29 Jan 2024 16:33:43 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 27,010 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>Tutorial - OWASP Node Goat Project</title> <!-- Bootstrap core CSS --> <link href="../vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Add custom CSS here --> <link href="../vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="../vendor/theme/font-awesome/css/font-awesome.min.css"> <!--[if lt IE 9]><script src="../vendor/html5shiv.js"><![endif]--> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/tutorial"><b>OWASP Node Goat Tutorial:</b> Fixing OWASP Top 10 </a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse navbar-ex1-collapse"> <ul class="nav navbar-nav side-nav"> <li><a href="/tutorial/a1"><i class="fa fa-wrench"></i> A1 Injection</a> </li> <li><a href="/tutorial/a2"><i class="fa fa-wrench"></i> A2 Broken Auth</a> </li> <li><a href="/tutorial/a3"><i class="fa fa-wrench"></i> A3 XSS</a> </li> <li><a href="/tutorial/a4"><i class="fa fa-wrench"></i> A4 Insecure DOR</a> </li> <li><a href="/tutorial/a5"><i class="fa fa-wrench"></i> A5 Misconfig</a> </li> <li><a href="/tutorial/a6"><i class="fa fa-wrench"></i> A6 Sensitive Data</a> </li> <li><a href="/tutorial/a7"><i class="fa fa-wrench"></i> A7 Access Controls</a> </li> <li><a href="/tutorial/a8"><i class="fa fa-wrench"></i> A8 CSRF</a> </li> <li><a href="/tutorial/a9"><i class="fa fa-wrench"></i> A9 Insecure Components</a> </li> <li><a href="/tutorial/a10"><i class="fa fa-wrench"></i> A10 Redirects</a> </li> <li><a href="/tutorial/redos"><i class="fa"></i> ReDoS Attacks</a> </li> <li><a href="/tutorial/ssrf"><i class="fa"></i> SSRF</a> </li> </ul> <ul class="nav navbar-nav navbar-right navbar-user"> <li><a href="/login"><i class="fa fa-power-off"></i> Exit</a> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <h1>A1 - Injection <small></small> </h1> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="bs-example" style="margin-bottom: 40px;"> <span class="label label-danger">Exploitability: EASY</span> <span class="label label-warning">Prevalence: COMMON</span> <span class="label label-warning">Detectability: AVERAGE</span> <span class="label label-danger">Technical Impact: SEVERE</span> </div> </div> </div> <div class="row"> <div class="col-lg-12"> <div class="panel panel-info"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> Injection flaws occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization. </div> </div> <!-- <div class="panel panel-info"> <div class="panel-heading"> <h3 class="panel-title">Real World Attack Incident Examples</h3> </div> <div class="panel-body"> Screencast here ... </div> </div> --> </div> </div> <!-- accordions --> <div class="panel-group" id="accordion"> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne"> <i class="fa fa-chevron-down"></i>A1 - 1 Server Side JS Injection </a> </h4> </div> <div id="collapseOne" class="panel-collapse collapse in"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> When <code>eval()</code>, <code>setTimeout()</code>, <code>setInterval()</code>, <code>Function()</code>are used to process user provided inputs, it can be exploited by an attacker to inject and execute malicious JavaScript code on server. </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p> Web applications using the JavaScript <code>eval()</code>function to parse the incoming data without any type of input validation are vulnerable to this attack. An attacker can inject arbitrary JavaScript code to be executed on the server. Similarly <code>setTimeout()</code>, and <code>setInterval()</code>functions can take code in string format as a first argument causing same issues as <code>eval()</code>. </p> <p>This vulnerability can be very critical and damaging by allowing attacker to send various types of commands.</p> <p> <b>Denial of Service Attack:</b> </p> <iframe width="560" height="315" src="//www.youtube.com/embed/krOx9QWwcYw?rel=0" frameborder="0" allowfullscreen></iframe> <p> An effective denial-of-service attack can be executed simply by sending the commands below to <code>eval()</code>function: </p> <pre>while(1)</pre> <p> This input will cause the target server's event loop to use 100% of its processor time and unable to process any other incoming requests until process is restarted. </p> <p> An alternative DoS attack would be to simply exit or kill the running process: <pre>process.exit()</pre> or <pre>process.kill(process.pid) </pre> </p> <p> <b>File System Access</b> <br/> </p> <iframe width="560" height="315" src="//www.youtube.com/embed/Mr-Jh9bjSLo?rel=0" frameborder="0" allowfullscreen></iframe> <p> Another potential goal of an attacker might be to read the contents of files from the server. For example, following two commands list the contents of the current directory and parent directory respectively: </p> <p> <pre>res.end(require('fs').readdirSync('.').toString())</pre> <pre>res.end(require('fs').readdirSync('..').toString()) </pre> </p> <p> Once file names are obtained, an attacker can issue the command below to view the actual contents of a file: </p> <p> <pre>res.end(require('fs').readFileSync(filename))</pre> </p> <p> An attacker can further exploit this vulnerability by writing and executing harmful binary files using <code>fs</code>and <code>child_process</code>modules. </p> </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> To prevent server-side js injection attacks: <ul> <li>Validate user inputs on server side before processing</li> <li>Do not use <code>eval()</code>function to parse user inputs. Avoid using other commands with similar effect, such as <code>setTimeOut()</code>, <code>setInterval()</code>, and <code>Function()</code>. </li> <li> For parsing JSON input, instead of using <code>eval()</code>, use a safer alternative such as <code>JSON.parse()</code>. For type conversions use type related <code>parseXXX()</code>methods. </li> <li>Include <code>"use strict"</code>at the beginning of a function, which enables <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode"> strict mode </a>within the enclosing function scope.</li> </ul> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p>In <code>routes/contributions.js</code>, the <code>handleContributionsUpdate()</code>function insecurely uses <code>eval()</code>to convert user supplied contribution amounts to integer. <pre> // Insecure use of eval() to parse inputs var preTax = eval(req.body.preTax); var afterTax = eval(req.body.afterTax); var roth = eval(req.body.roth); </pre> This makes application vulnerable to SSJS attack. It can fixed simply by using <code>parseInt()</code>instead. <pre> //Fix for A1 -1 SSJS Injection attacks - uses alternate method to eval var preTax = parseInt(req.body.preTax); var afterTax = parseInt(req.body.afterTax); var roth = parseInt(req.body.roth); </pre> </p> <p>In addition, all functions begin with <code>use strict</code>pragma. </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Further Reading</h3> </div> <div class="panel-body"> <ul> <li><a target="_blank" href="https://media.blackhat.com/bh-us-11/Sullivan/BH_US_11_Sullivan_Server_Side_WP.pdf">“ServerSide JavaScript Injection: Attacking NoSQL and Node.js"</a> a whitepaper by Bryan Sullivan.</li> </ul> </div> </div> </div> </div> </div> <!-- /ssjs --> <!-- DB Injection --> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo"> <i class="fa fa-chevron-down"></i> A1 - 2 SQL and NoSQL Injection </a> </h4> </div> <div id="collapseTwo" class="panel-collapse"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> <p> SQL and NoSQL injections enable an attacker to inject code into the query that would be executed by the database. These flaws are introduced when software developers create dynamic database queries that include user supplied input. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p>Both SQL and NoSQL databases are vulnerable to injection attack. Here is an example of equivalent attack in both cases, where attacker manages to retrieve admin user's record without knowing password:</p> <h5>1. SQL Injection</h5> <p>Lets consider an example SQL statement used to authenticate the user with username and password</p> <pre>SELECT * FROM accounts WHERE username = '$username' AND password = '$password'</pre> <p>If this statement is not prepared or properly handled when constructed, an attacker may be able to supply <code>admin' --</code>in the username field to access the admin user's account bypassing the condition that checks for the password. The resultant SQL query would looks like:</p> <pre>SELECT * FROM accounts WHERE username = 'admin' -- AND password = ''</pre> <br/> <h5>2. NoSQL Injection</h5> <p>The equivalent of above query for NoSQL MongoDB database is:</p> <pre>db.accounts.find({username: username, password: password});</pre> <p>While here we are no longer dealing with query language, an attacker can still achieve the same results as SQL injection by supplying JSON input object as below:</p> <pre> { "username": "admin", "password": {$gt: ""} } </pre> <p>In MongoDB, <code>$gt</code>selects those documents where the value of the field is greater than (i.e. >) the specified value. Thus above statement compares password in database with empty string for greatness, which returns <code>true</code>.</p> <p>The same results can be achieved using other comparison operator such as <code>$ne</code>.</p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">SSJS Attack Mechanics</h3> </div> <div class="panel-body"> <p> Server-side JavaScript Injection (SSJS) is an attack where JavaScript code is injected and executed in a server component. MongoDB specifically, is vulnerable to this attack when queries are run without proper sanitization. </p> <h5>$where operator</h5> <p> MongoDB's <code>$where</code> operator performs JavaScript expression evaluation on the MongoDB server. If the user is able to inject direct code into such queries then such an attack can take place </p> <p> Lets consider an example query: </p> <pre> db.allocationsCollection.find({ $where: "this.userId == '" + parsedUserId + "' && " + "this.stocks > " + "'" + threshold + "'" }); </pre> <p> The code will match all documents which have a <code>userId</code> field as specified by <code>parsedUserId</code> and a <code>stocks</code> field as specified by <code>threshold</code>. The problem is that these parameters are not validated, filtered, or sanitised, and vulnerable to SSJS Injection. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> Here are some measures to prevent SQL / NoSQL injection attacks, or minimize impact if it happens: <ul> <li>Prepared Statements: For SQL calls, use prepared statements instead of building dynamic queries using string concatenation.</li> <li>Input Validation: Validate inputs to detect malicious values. For NoSQL databases, also validate input types against expected types</li> <li>Least Privilege: To minimize the potential damage of a successful injection attack, do not assign DBA or admin type access rights to your application accounts. Similarly minimize the privileges of the operating system account that the database process runs under.</li> </ul> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p><strong>Note: These vulnerabilities are not present when using an Atlas M0 cluster with NodeGoat.</strong></p> <p>The Allocations page of the demo application is vulnerable to NoSQL Injection. For example, set the stocks threshold filter to:</p> <pre>1'; return 1 == '1</pre> <p>This will retrieve allocations for all the users in the database.</p> <p>An attacker could also send the following input for the <code>threshold</code> field in the request's query, which will create a valid JavaScript expression and satisfy the <code> $where</code> query as well, resulting in a DoS attack on the MongoDB server: </p> <pre>http://localhost:4000/allocations/2?threshold=5';while(true){};' </pre> <p> You can also just drop the following into the Stocks Threshold input box: </p> <pre>';while(true){};'</pre> <p>For these vulnerabilities, bare minimum fixes can be found in <code>allocations.html</code> and <code>allocations-dao.js</code></p> </div> </div> </div> </div> </div> <!-- /NoSQL Injection --> <!-- Log Injection --> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree"> <i class="fa fa-chevron-down"></i> A1 - 3 Log Injection </a> </h4> </div> <div id="collapseThree" class="panel-collapse"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> <p> Log injection vulnerabilities enable an attacker to forge and tamper with an application's logs. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p>An attacker may craft a malicious request that may deliberately fail, which the application will log, and when attacker's user input is unsanitized, the payload is sent as-is to the logging facility. Vulnerabilities may vary depending on the logging facility:</p> <h5>1. Log Forging (CRLF) </h5> <p>Lets consider an example where an application logs a failed attempt to login to the system. A very common example for this is as follows: </p> <pre> var userName = req.body.userName; console.log('Error: attempt to login with invalid user: ', userName); </pre> <p>When user input is unsanitized and the output mechanism is an ordinary terminal stdout facility then the application will be vulnerable to CRLF injection, where an attacker can create a malicious payload as follows: <pre> curl http://localhost:4000/login -X POST --data 'userName=vyva%0aError: alex moldovan failed $1,000,000 transaction&password=Admin_123&_csrf=' </pre> Where the <code>userName</code> parameter is encoding in the request the LF symbol which will result in a new line to begin. Resulting log output will look as follows: <pre> Error: attempt to login with invalid user: vyva Error: alex moldovan failed $1,000,000 transaction </pre> <br/> <h5>2. Log Injection Escalation </h5> <p> An attacker may craft malicious input in hope of an escalated attack where the target isn't the logs themselves, but rather the actual logging system. For example, if an application has a back-office web app that manages viewing and tracking the logs, then an attacker may send an XSS payload into the log, which may not result in log forging on the log itself, but when viewed by a system administrator on the log viewing web app then it may compromise it and result in XSS injection that if the logs app is vulnerable. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> As always when dealing with user input: <ul> <li> Do not allow user input into logs </li> <li> Encode to proper context, or sanitize user input </li> </ul> Encoding example: <pre> // Step 1: Require a module that supports encoding var ESAPI = require('node-esapi'); // - Step 2: Encode the user input that will be logged in the correct context // following are a few examples: console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForHTML(userName)); console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForJavaScript(userName)); console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForURL(userName)); </pre> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p>For the above Log Injection vulnerability, example and fix can be found at <code>routes/session.js</code></p> </div> </div> </div> </div> </div> <!-- /Log Injection --> </div> <!-- end accordions --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <script src="../vendor/jquery.min.js"></script> <script src="../vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/login |
| Method | POST |
| Parameter | |
| Attack | |
| Evidence | |
| Request Header - size: 697 bytes. |
POST http://jenkins_docker-compose_application_web_1:4000/login HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Content-Type: application/x-www-form-urlencoded Content-Length: 34 Origin: http://jenkins_docker-compose_application_web_1:4000 Connection: keep-alive Cookie: connect.sid=s%3AyGMSRGNYEF-6z61RLvRrrBNTAh_dtQGn.53w2hKRBLZfOMBxxohiuNfCoghCrZtv7qOJEujRc5IM Upgrade-Insecure-Requests: 1 |
| Request Body - size: 34 bytes. |
userName=HhyVAgNS&password=&_csrf=
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 7514 ETag: W/"1d5a-vBvXIMawvps2XiuMx1Ih4luZS3I" Date: Mon, 29 Jan 2024 16:33:48 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 7,514 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="OWASP NodeGoat Project: Insecure App"> <meta name="version" content="v1.2"> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="https://www.owasp.org/index.php/Projects/OWASP_Node_js_Goat_Project">OWASP Node Goat Project</a> </div> <!-- Nav Links--> <div class="collapse navbar-collapse navbar-ex1-collapse"> <!-- top nav --> <ul class="nav navbar-nav navbar-right navbar-user"> <li class="dropdown user-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" style="font-size: larger"><i class="fa fa-info-circle"></i></a> <ul class="dropdown-menu alert-dropdown" style="min-width: 350px; padding: 10px"> <li> <p> The OWASP Node Goat is an educational Node.js web application vulnerable to the <a target="_blank" href="https://www.owasp.org/index.php/Top_10_2013-Top_10"> OWASP Top 10</a> risks.</p> <p>It is intended to show how each of these vulnerabilities can manifest in a Node.js specific way, and provides the subsequent mitigation for each with source code examples. </p> <p>To start hacking the application, login using the form below, or access the tutorial guide to know more.</p> </li> <li class="divider"></li> <li style="text-align: right"> <i class="fa fa-tag"> </i> v1.2 </li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div style="text-align: center; padding: 30px"> <img src="/images/owasplogo.png" height="80px"> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-4"></div> <div class="col-lg-4"> <div class="panel panel-info"> <div class="panel-heading" style="text-align: center"> <a href="/tutorial" target="_blank"> <b><span class="fa fa-book"></span> Tutorial Guide:</b> Learn OWASP Top 10 </a> </div> </div> <div class="panel panel-default"> <div class="panel-heading" style="text-align: center"> <span style="font-size: x-large"> <span class="fa fa-bullseye"></span>Retire<b>Easy</b> </span> <br /> <span style="font-size: medium">Employee Retirement Savings Management</span> <br /> <br /> </div> <div class="panel-body"> <div class="alert alert-dismissable alert-danger"> <button type="button" class="close" data-dismiss="alert">×</button> Invalid username </div> <form method="post" role="form" method="post" id="loginform"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" name="userName" value="HhyVAgNS" placeholder="Enter User Name"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter Password"> </div> <input type="hidden" name="_csrf" value="" /> <div class="row"> <div class="col-lg-4"><a href="/signup">New user? Sign Up</a> </div> <div class="col-lg-5"></div> <div class="col-lg-3"> <button type="submit" class="btn btn-danger">Submit</button> </div> </div> </form> </div> </div> </div> <div class="col-lg-4"></div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> <!-- /.row --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> <script type="application/javascript"> const areCookiesEnabled = () => { const cookieEnabled = navigator.cookieEnabled; // When cookieEnabled flag is present and false then cookies are disabled. if (!cookieEnabled) return false; // try to set a test cookie if we can't see any cookies and we're using // either a browser that doesn't support navigator.cookieEnabled // or IE (which always returns true for navigator.cookieEnabled) if (!document.cookie && cookieEnabled === null) { document.cookie = "testcookie=1"; if (!document.cookie) return false; document.cookie = "testcookie=; expires=" + new Date(0).toUTCString(); } return true; } $(document).ready(() => { if (!areCookiesEnabled()) { $("#page-wrapper").prepend("<div class=\"row\"><div class=\"col-lg-12\"><div class=\"alert alert-danger\">Cookies are not enabled on your browser. Please enable cookies in your browser preferences to continue.</div></div></div>"); } }); </script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/signup |
| Method | POST |
| Parameter | |
| Attack | |
| Evidence | |
| Request Header - size: 701 bytes. |
POST http://jenkins_docker-compose_application_web_1:4000/signup HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/signup Content-Type: application/x-www-form-urlencoded Content-Length: 86 Origin: http://jenkins_docker-compose_application_web_1:4000 Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg Upgrade-Insecure-Requests: 1 |
| Request Body - size: 86 bytes. |
userName=ECeNuwfl&firstName=zAuRhWJS&lastName=GuQMUShW&password=&verify=&email=&_csrf=
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 4999 ETag: W/"1387-k/xYlSuNY0T8Jt7I4fy0VJVIBXA" Date: Mon, 29 Jan 2024 16:33:58 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 4,999 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <!-- Add custom CSS here --> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="/">OWASP Node Goat Project</a> </div> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div class="well well-sm"> Already a user? <a href="/login">Login</a> <p> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="alert alert-dismissable alert-danger"> <button type="button" class="close" data-dismiss="alert">×</button> <p>Password must be 8 to 18 characters including numbers, lowercase and uppercase letters.</p> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Enter sign up information</h3> </div> <div class="panel-body"> <form method="post" role="form" method="post"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" value="ECeNuwfl" name="userName" placeholder="Enter user name"> </div> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" value="" name="firstName" placeholder="Enter first name"> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" value="" name="lastName" placeholder="Enter last name"> </div> <div class="form-group"> <label for="lastname">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Verify Password</label> <input type="password" class="form-control" id="verify" name="verify" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Email (Optional)</label> <input type="email" class="form-control" id="email" name="email" value="" placeholder="Enter email"> </div> <input type="hidden" name="_csrf" value=""></input> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| Instances | 6 |
| Solution |
Ensure that your web server, application server, load balancer, etc. is configured to set the Content-Security-Policy header.
|
| Reference |
https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Introducing_Content_Security_Policy
https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html http://www.w3.org/TR/CSP/ http://w3c.github.io/webappsec/specs/content-security-policy/csp-specification.dev.html http://www.html5rocks.com/en/tutorials/security/content-security-policy/ http://caniuse.com/#feat=contentsecuritypolicy http://content-security-policy.com/ |
| Tags |
OWASP_2021_A05
OWASP_2017_A06 |
| CWE Id | 693 |
| WASC Id | 15 |
| Plugin Id | 10038 |
|
Medium |
Directory Browsing |
|---|---|
| Description |
It is possible to view the directory listing. Directory listing may reveal hidden scripts, include files, backup source files, etc. which can be accessed to read sensitive information.
|
| URL | http://jenkins_docker-compose_application_web_1:4000/tutorial/ |
| Method | GET |
| Parameter | |
| Attack | http://jenkins_docker-compose_application_web_1:4000/tutorial/ |
| Evidence | parent directory |
| Request Header - size: 573 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/tutorial/ HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Connection: keep-alive Cookie: connect.sid=s%3A6l4x9lvFSBO3eZCtcIaSh1m9xH73hlif.%2FKVneLbM19x9O8l4PH%2BJdUKdkH3mt5ZwclTb52i24zk Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 233 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 27010 ETag: W/"6982-Li2JuR00Z8ulcGovuWWgt5WzEqM" Date: Mon, 29 Jan 2024 16:43:20 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 27,010 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>Tutorial - OWASP Node Goat Project</title> <!-- Bootstrap core CSS --> <link href="../vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Add custom CSS here --> <link href="../vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="../vendor/theme/font-awesome/css/font-awesome.min.css"> <!--[if lt IE 9]><script src="../vendor/html5shiv.js"><![endif]--> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/tutorial"><b>OWASP Node Goat Tutorial:</b> Fixing OWASP Top 10 </a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse navbar-ex1-collapse"> <ul class="nav navbar-nav side-nav"> <li><a href="/tutorial/a1"><i class="fa fa-wrench"></i> A1 Injection</a> </li> <li><a href="/tutorial/a2"><i class="fa fa-wrench"></i> A2 Broken Auth</a> </li> <li><a href="/tutorial/a3"><i class="fa fa-wrench"></i> A3 XSS</a> </li> <li><a href="/tutorial/a4"><i class="fa fa-wrench"></i> A4 Insecure DOR</a> </li> <li><a href="/tutorial/a5"><i class="fa fa-wrench"></i> A5 Misconfig</a> </li> <li><a href="/tutorial/a6"><i class="fa fa-wrench"></i> A6 Sensitive Data</a> </li> <li><a href="/tutorial/a7"><i class="fa fa-wrench"></i> A7 Access Controls</a> </li> <li><a href="/tutorial/a8"><i class="fa fa-wrench"></i> A8 CSRF</a> </li> <li><a href="/tutorial/a9"><i class="fa fa-wrench"></i> A9 Insecure Components</a> </li> <li><a href="/tutorial/a10"><i class="fa fa-wrench"></i> A10 Redirects</a> </li> <li><a href="/tutorial/redos"><i class="fa"></i> ReDoS Attacks</a> </li> <li><a href="/tutorial/ssrf"><i class="fa"></i> SSRF</a> </li> </ul> <ul class="nav navbar-nav navbar-right navbar-user"> <li><a href="/login"><i class="fa fa-power-off"></i> Exit</a> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <h1>A1 - Injection <small></small> </h1> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="bs-example" style="margin-bottom: 40px;"> <span class="label label-danger">Exploitability: EASY</span> <span class="label label-warning">Prevalence: COMMON</span> <span class="label label-warning">Detectability: AVERAGE</span> <span class="label label-danger">Technical Impact: SEVERE</span> </div> </div> </div> <div class="row"> <div class="col-lg-12"> <div class="panel panel-info"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> Injection flaws occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization. </div> </div> <!-- <div class="panel panel-info"> <div class="panel-heading"> <h3 class="panel-title">Real World Attack Incident Examples</h3> </div> <div class="panel-body"> Screencast here ... </div> </div> --> </div> </div> <!-- accordions --> <div class="panel-group" id="accordion"> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne"> <i class="fa fa-chevron-down"></i>A1 - 1 Server Side JS Injection </a> </h4> </div> <div id="collapseOne" class="panel-collapse collapse in"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> When <code>eval()</code>, <code>setTimeout()</code>, <code>setInterval()</code>, <code>Function()</code>are used to process user provided inputs, it can be exploited by an attacker to inject and execute malicious JavaScript code on server. </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p> Web applications using the JavaScript <code>eval()</code>function to parse the incoming data without any type of input validation are vulnerable to this attack. An attacker can inject arbitrary JavaScript code to be executed on the server. Similarly <code>setTimeout()</code>, and <code>setInterval()</code>functions can take code in string format as a first argument causing same issues as <code>eval()</code>. </p> <p>This vulnerability can be very critical and damaging by allowing attacker to send various types of commands.</p> <p> <b>Denial of Service Attack:</b> </p> <iframe width="560" height="315" src="//www.youtube.com/embed/krOx9QWwcYw?rel=0" frameborder="0" allowfullscreen></iframe> <p> An effective denial-of-service attack can be executed simply by sending the commands below to <code>eval()</code>function: </p> <pre>while(1)</pre> <p> This input will cause the target server's event loop to use 100% of its processor time and unable to process any other incoming requests until process is restarted. </p> <p> An alternative DoS attack would be to simply exit or kill the running process: <pre>process.exit()</pre> or <pre>process.kill(process.pid) </pre> </p> <p> <b>File System Access</b> <br/> </p> <iframe width="560" height="315" src="//www.youtube.com/embed/Mr-Jh9bjSLo?rel=0" frameborder="0" allowfullscreen></iframe> <p> Another potential goal of an attacker might be to read the contents of files from the server. For example, following two commands list the contents of the current directory and parent directory respectively: </p> <p> <pre>res.end(require('fs').readdirSync('.').toString())</pre> <pre>res.end(require('fs').readdirSync('..').toString()) </pre> </p> <p> Once file names are obtained, an attacker can issue the command below to view the actual contents of a file: </p> <p> <pre>res.end(require('fs').readFileSync(filename))</pre> </p> <p> An attacker can further exploit this vulnerability by writing and executing harmful binary files using <code>fs</code>and <code>child_process</code>modules. </p> </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> To prevent server-side js injection attacks: <ul> <li>Validate user inputs on server side before processing</li> <li>Do not use <code>eval()</code>function to parse user inputs. Avoid using other commands with similar effect, such as <code>setTimeOut()</code>, <code>setInterval()</code>, and <code>Function()</code>. </li> <li> For parsing JSON input, instead of using <code>eval()</code>, use a safer alternative such as <code>JSON.parse()</code>. For type conversions use type related <code>parseXXX()</code>methods. </li> <li>Include <code>"use strict"</code>at the beginning of a function, which enables <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode"> strict mode </a>within the enclosing function scope.</li> </ul> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p>In <code>routes/contributions.js</code>, the <code>handleContributionsUpdate()</code>function insecurely uses <code>eval()</code>to convert user supplied contribution amounts to integer. <pre> // Insecure use of eval() to parse inputs var preTax = eval(req.body.preTax); var afterTax = eval(req.body.afterTax); var roth = eval(req.body.roth); </pre> This makes application vulnerable to SSJS attack. It can fixed simply by using <code>parseInt()</code>instead. <pre> //Fix for A1 -1 SSJS Injection attacks - uses alternate method to eval var preTax = parseInt(req.body.preTax); var afterTax = parseInt(req.body.afterTax); var roth = parseInt(req.body.roth); </pre> </p> <p>In addition, all functions begin with <code>use strict</code>pragma. </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Further Reading</h3> </div> <div class="panel-body"> <ul> <li><a target="_blank" href="https://media.blackhat.com/bh-us-11/Sullivan/BH_US_11_Sullivan_Server_Side_WP.pdf">“ServerSide JavaScript Injection: Attacking NoSQL and Node.js"</a> a whitepaper by Bryan Sullivan.</li> </ul> </div> </div> </div> </div> </div> <!-- /ssjs --> <!-- DB Injection --> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo"> <i class="fa fa-chevron-down"></i> A1 - 2 SQL and NoSQL Injection </a> </h4> </div> <div id="collapseTwo" class="panel-collapse"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> <p> SQL and NoSQL injections enable an attacker to inject code into the query that would be executed by the database. These flaws are introduced when software developers create dynamic database queries that include user supplied input. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p>Both SQL and NoSQL databases are vulnerable to injection attack. Here is an example of equivalent attack in both cases, where attacker manages to retrieve admin user's record without knowing password:</p> <h5>1. SQL Injection</h5> <p>Lets consider an example SQL statement used to authenticate the user with username and password</p> <pre>SELECT * FROM accounts WHERE username = '$username' AND password = '$password'</pre> <p>If this statement is not prepared or properly handled when constructed, an attacker may be able to supply <code>admin' --</code>in the username field to access the admin user's account bypassing the condition that checks for the password. The resultant SQL query would looks like:</p> <pre>SELECT * FROM accounts WHERE username = 'admin' -- AND password = ''</pre> <br/> <h5>2. NoSQL Injection</h5> <p>The equivalent of above query for NoSQL MongoDB database is:</p> <pre>db.accounts.find({username: username, password: password});</pre> <p>While here we are no longer dealing with query language, an attacker can still achieve the same results as SQL injection by supplying JSON input object as below:</p> <pre> { "username": "admin", "password": {$gt: ""} } </pre> <p>In MongoDB, <code>$gt</code>selects those documents where the value of the field is greater than (i.e. >) the specified value. Thus above statement compares password in database with empty string for greatness, which returns <code>true</code>.</p> <p>The same results can be achieved using other comparison operator such as <code>$ne</code>.</p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">SSJS Attack Mechanics</h3> </div> <div class="panel-body"> <p> Server-side JavaScript Injection (SSJS) is an attack where JavaScript code is injected and executed in a server component. MongoDB specifically, is vulnerable to this attack when queries are run without proper sanitization. </p> <h5>$where operator</h5> <p> MongoDB's <code>$where</code> operator performs JavaScript expression evaluation on the MongoDB server. If the user is able to inject direct code into such queries then such an attack can take place </p> <p> Lets consider an example query: </p> <pre> db.allocationsCollection.find({ $where: "this.userId == '" + parsedUserId + "' && " + "this.stocks > " + "'" + threshold + "'" }); </pre> <p> The code will match all documents which have a <code>userId</code> field as specified by <code>parsedUserId</code> and a <code>stocks</code> field as specified by <code>threshold</code>. The problem is that these parameters are not validated, filtered, or sanitised, and vulnerable to SSJS Injection. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> Here are some measures to prevent SQL / NoSQL injection attacks, or minimize impact if it happens: <ul> <li>Prepared Statements: For SQL calls, use prepared statements instead of building dynamic queries using string concatenation.</li> <li>Input Validation: Validate inputs to detect malicious values. For NoSQL databases, also validate input types against expected types</li> <li>Least Privilege: To minimize the potential damage of a successful injection attack, do not assign DBA or admin type access rights to your application accounts. Similarly minimize the privileges of the operating system account that the database process runs under.</li> </ul> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p><strong>Note: These vulnerabilities are not present when using an Atlas M0 cluster with NodeGoat.</strong></p> <p>The Allocations page of the demo application is vulnerable to NoSQL Injection. For example, set the stocks threshold filter to:</p> <pre>1'; return 1 == '1</pre> <p>This will retrieve allocations for all the users in the database.</p> <p>An attacker could also send the following input for the <code>threshold</code> field in the request's query, which will create a valid JavaScript expression and satisfy the <code> $where</code> query as well, resulting in a DoS attack on the MongoDB server: </p> <pre>http://localhost:4000/allocations/2?threshold=5';while(true){};' </pre> <p> You can also just drop the following into the Stocks Threshold input box: </p> <pre>';while(true){};'</pre> <p>For these vulnerabilities, bare minimum fixes can be found in <code>allocations.html</code> and <code>allocations-dao.js</code></p> </div> </div> </div> </div> </div> <!-- /NoSQL Injection --> <!-- Log Injection --> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree"> <i class="fa fa-chevron-down"></i> A1 - 3 Log Injection </a> </h4> </div> <div id="collapseThree" class="panel-collapse"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> <p> Log injection vulnerabilities enable an attacker to forge and tamper with an application's logs. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p>An attacker may craft a malicious request that may deliberately fail, which the application will log, and when attacker's user input is unsanitized, the payload is sent as-is to the logging facility. Vulnerabilities may vary depending on the logging facility:</p> <h5>1. Log Forging (CRLF) </h5> <p>Lets consider an example where an application logs a failed attempt to login to the system. A very common example for this is as follows: </p> <pre> var userName = req.body.userName; console.log('Error: attempt to login with invalid user: ', userName); </pre> <p>When user input is unsanitized and the output mechanism is an ordinary terminal stdout facility then the application will be vulnerable to CRLF injection, where an attacker can create a malicious payload as follows: <pre> curl http://localhost:4000/login -X POST --data 'userName=vyva%0aError: alex moldovan failed $1,000,000 transaction&password=Admin_123&_csrf=' </pre> Where the <code>userName</code> parameter is encoding in the request the LF symbol which will result in a new line to begin. Resulting log output will look as follows: <pre> Error: attempt to login with invalid user: vyva Error: alex moldovan failed $1,000,000 transaction </pre> <br/> <h5>2. Log Injection Escalation </h5> <p> An attacker may craft malicious input in hope of an escalated attack where the target isn't the logs themselves, but rather the actual logging system. For example, if an application has a back-office web app that manages viewing and tracking the logs, then an attacker may send an XSS payload into the log, which may not result in log forging on the log itself, but when viewed by a system administrator on the log viewing web app then it may compromise it and result in XSS injection that if the logs app is vulnerable. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> As always when dealing with user input: <ul> <li> Do not allow user input into logs </li> <li> Encode to proper context, or sanitize user input </li> </ul> Encoding example: <pre> // Step 1: Require a module that supports encoding var ESAPI = require('node-esapi'); // - Step 2: Encode the user input that will be logged in the correct context // following are a few examples: console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForHTML(userName)); console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForJavaScript(userName)); console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForURL(userName)); </pre> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p>For the above Log Injection vulnerability, example and fix can be found at <code>routes/session.js</code></p> </div> </div> </div> </div> </div> <!-- /Log Injection --> </div> <!-- end accordions --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <script src="../vendor/jquery.min.js"></script> <script src="../vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| Instances | 1 |
| Solution |
Disable directory browsing. If this is required, make sure the listed files does not induce risks.
|
| Reference |
http://httpd.apache.org/docs/mod/core.html#options
http://alamo.satlug.org/pipermail/satlug/2002-February/000053.html |
| Tags |
OWASP_2021_A01
OWASP_2017_A05 |
| CWE Id | 548 |
| WASC Id | 48 |
| Plugin Id | 0 |
|
Medium |
Missing Anti-clickjacking Header |
|---|---|
| Description |
The response does not include either Content-Security-Policy with 'frame-ancestors' directive or X-Frame-Options to protect against 'ClickJacking' attacks.
|
| URL | http://jenkins_docker-compose_application_web_1:4000 |
| Method | GET |
| Parameter | x-frame-options |
| Attack | |
| Evidence | |
| Request Header - size: 290 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000 HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 360 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 7208 ETag: W/"1c28-jzMKoc+DPSvVfJwC7jYRDNnpaUs" set-cookie: connect.sid=s%3AQwLdXMcnkQaq6YvZvtTYL4BnMHb9eAv4.NEqu3dKtNsc%2F4nMbEdjeASDgie%2Bfj1FBoAOQDFNalTo; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 7,208 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="OWASP NodeGoat Project: Insecure App"> <meta name="version" content="v1.2"> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="https://www.owasp.org/index.php/Projects/OWASP_Node_js_Goat_Project">OWASP Node Goat Project</a> </div> <!-- Nav Links--> <div class="collapse navbar-collapse navbar-ex1-collapse"> <!-- top nav --> <ul class="nav navbar-nav navbar-right navbar-user"> <li class="dropdown user-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" style="font-size: larger"><i class="fa fa-info-circle"></i></a> <ul class="dropdown-menu alert-dropdown" style="min-width: 350px; padding: 10px"> <li> <p> The OWASP Node Goat is an educational Node.js web application vulnerable to the <a target="_blank" href="https://www.owasp.org/index.php/Top_10_2013-Top_10"> OWASP Top 10</a> risks.</p> <p>It is intended to show how each of these vulnerabilities can manifest in a Node.js specific way, and provides the subsequent mitigation for each with source code examples. </p> <p>To start hacking the application, login using the form below, or access the tutorial guide to know more.</p> </li> <li class="divider"></li> <li style="text-align: right"> <i class="fa fa-tag"> </i> v1.2 </li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div style="text-align: center; padding: 30px"> <img src="/images/owasplogo.png" height="80px"> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-4"></div> <div class="col-lg-4"> <div class="panel panel-info"> <div class="panel-heading" style="text-align: center"> <a href="/tutorial" target="_blank"> <b><span class="fa fa-book"></span> Tutorial Guide:</b> Learn OWASP Top 10 </a> </div> </div> <div class="panel panel-default"> <div class="panel-heading" style="text-align: center"> <span style="font-size: x-large"> <span class="fa fa-bullseye"></span>Retire<b>Easy</b> </span> <br /> <span style="font-size: medium">Employee Retirement Savings Management</span> <br /> <br /> </div> <div class="panel-body"> <form method="post" role="form" method="post" id="loginform"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" name="userName" value="" placeholder="Enter User Name"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter Password"> </div> <input type="hidden" name="_csrf" value="" /> <div class="row"> <div class="col-lg-4"><a href="/signup">New user? Sign Up</a> </div> <div class="col-lg-5"></div> <div class="col-lg-3"> <button type="submit" class="btn btn-danger">Submit</button> </div> </div> </form> </div> </div> </div> <div class="col-lg-4"></div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> <!-- /.row --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> <script type="application/javascript"> const areCookiesEnabled = () => { const cookieEnabled = navigator.cookieEnabled; // When cookieEnabled flag is present and false then cookies are disabled. if (!cookieEnabled) return false; // try to set a test cookie if we can't see any cookies and we're using // either a browser that doesn't support navigator.cookieEnabled // or IE (which always returns true for navigator.cookieEnabled) if (!document.cookie && cookieEnabled === null) { document.cookie = "testcookie=1"; if (!document.cookie) return false; document.cookie = "testcookie=; expires=" + new Date(0).toUTCString(); } return true; } $(document).ready(() => { if (!areCookiesEnabled()) { $("#page-wrapper").prepend("<div class=\"row\"><div class=\"col-lg-12\"><div class=\"alert alert-danger\">Cookies are not enabled on your browser. Please enable cookies in your browser preferences to continue.</div></div></div>"); } }); </script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/login |
| Method | GET |
| Parameter | x-frame-options |
| Attack | |
| Evidence | |
| Request Header - size: 498 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/login HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 7208 ETag: W/"1c28-jzMKoc+DPSvVfJwC7jYRDNnpaUs" Date: Mon, 29 Jan 2024 16:33:31 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 7,208 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="OWASP NodeGoat Project: Insecure App"> <meta name="version" content="v1.2"> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="https://www.owasp.org/index.php/Projects/OWASP_Node_js_Goat_Project">OWASP Node Goat Project</a> </div> <!-- Nav Links--> <div class="collapse navbar-collapse navbar-ex1-collapse"> <!-- top nav --> <ul class="nav navbar-nav navbar-right navbar-user"> <li class="dropdown user-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" style="font-size: larger"><i class="fa fa-info-circle"></i></a> <ul class="dropdown-menu alert-dropdown" style="min-width: 350px; padding: 10px"> <li> <p> The OWASP Node Goat is an educational Node.js web application vulnerable to the <a target="_blank" href="https://www.owasp.org/index.php/Top_10_2013-Top_10"> OWASP Top 10</a> risks.</p> <p>It is intended to show how each of these vulnerabilities can manifest in a Node.js specific way, and provides the subsequent mitigation for each with source code examples. </p> <p>To start hacking the application, login using the form below, or access the tutorial guide to know more.</p> </li> <li class="divider"></li> <li style="text-align: right"> <i class="fa fa-tag"> </i> v1.2 </li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div style="text-align: center; padding: 30px"> <img src="/images/owasplogo.png" height="80px"> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-4"></div> <div class="col-lg-4"> <div class="panel panel-info"> <div class="panel-heading" style="text-align: center"> <a href="/tutorial" target="_blank"> <b><span class="fa fa-book"></span> Tutorial Guide:</b> Learn OWASP Top 10 </a> </div> </div> <div class="panel panel-default"> <div class="panel-heading" style="text-align: center"> <span style="font-size: x-large"> <span class="fa fa-bullseye"></span>Retire<b>Easy</b> </span> <br /> <span style="font-size: medium">Employee Retirement Savings Management</span> <br /> <br /> </div> <div class="panel-body"> <form method="post" role="form" method="post" id="loginform"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" name="userName" value="" placeholder="Enter User Name"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter Password"> </div> <input type="hidden" name="_csrf" value="" /> <div class="row"> <div class="col-lg-4"><a href="/signup">New user? Sign Up</a> </div> <div class="col-lg-5"></div> <div class="col-lg-3"> <button type="submit" class="btn btn-danger">Submit</button> </div> </div> </form> </div> </div> </div> <div class="col-lg-4"></div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> <!-- /.row --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> <script type="application/javascript"> const areCookiesEnabled = () => { const cookieEnabled = navigator.cookieEnabled; // When cookieEnabled flag is present and false then cookies are disabled. if (!cookieEnabled) return false; // try to set a test cookie if we can't see any cookies and we're using // either a browser that doesn't support navigator.cookieEnabled // or IE (which always returns true for navigator.cookieEnabled) if (!document.cookie && cookieEnabled === null) { document.cookie = "testcookie=1"; if (!document.cookie) return false; document.cookie = "testcookie=; expires=" + new Date(0).toUTCString(); } return true; } $(document).ready(() => { if (!areCookiesEnabled()) { $("#page-wrapper").prepend("<div class=\"row\"><div class=\"col-lg-12\"><div class=\"alert alert-danger\">Cookies are not enabled on your browser. Please enable cookies in your browser preferences to continue.</div></div></div>"); } }); </script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/signup |
| Method | GET |
| Parameter | x-frame-options |
| Attack | |
| Evidence | |
| Request Header - size: 570 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/signup HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Connection: keep-alive Cookie: connect.sid=s%3AIF9C8qOuAKIcRfBbQqlCJJXkbklBl-qx.oP%2BOVOd6OEM180NJJ02GnInP0AWbC%2BM6FRljTBVrJ0U Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 4551 ETag: W/"11c7-Y/9Bw9cdVN5/8qERn0VzdrK/7QY" Date: Mon, 29 Jan 2024 16:33:44 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 4,551 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <!-- Add custom CSS here --> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="/">OWASP Node Goat Project</a> </div> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div class="well well-sm"> Already a user? <a href="/login">Login</a> <p> </div> </div> </div> <!-- /.row --> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Enter sign up information</h3> </div> <div class="panel-body"> <form method="post" role="form" method="post"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" value="" name="userName" placeholder="Enter user name"> </div> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" value="" name="firstName" placeholder="Enter first name"> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" value="" name="lastName" placeholder="Enter last name"> </div> <div class="form-group"> <label for="lastname">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Verify Password</label> <input type="password" class="form-control" id="verify" name="verify" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Email (Optional)</label> <input type="email" class="form-control" id="email" name="email" value="" placeholder="Enter email"> </div> <input type="hidden" name="_csrf" value=""></input> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/tutorial |
| Method | GET |
| Parameter | x-frame-options |
| Attack | |
| Evidence | |
| Request Header - size: 570 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/tutorial HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 233 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 27010 ETag: W/"6982-Li2JuR00Z8ulcGovuWWgt5WzEqM" Date: Mon, 29 Jan 2024 16:33:43 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 27,010 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>Tutorial - OWASP Node Goat Project</title> <!-- Bootstrap core CSS --> <link href="../vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Add custom CSS here --> <link href="../vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="../vendor/theme/font-awesome/css/font-awesome.min.css"> <!--[if lt IE 9]><script src="../vendor/html5shiv.js"><![endif]--> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/tutorial"><b>OWASP Node Goat Tutorial:</b> Fixing OWASP Top 10 </a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse navbar-ex1-collapse"> <ul class="nav navbar-nav side-nav"> <li><a href="/tutorial/a1"><i class="fa fa-wrench"></i> A1 Injection</a> </li> <li><a href="/tutorial/a2"><i class="fa fa-wrench"></i> A2 Broken Auth</a> </li> <li><a href="/tutorial/a3"><i class="fa fa-wrench"></i> A3 XSS</a> </li> <li><a href="/tutorial/a4"><i class="fa fa-wrench"></i> A4 Insecure DOR</a> </li> <li><a href="/tutorial/a5"><i class="fa fa-wrench"></i> A5 Misconfig</a> </li> <li><a href="/tutorial/a6"><i class="fa fa-wrench"></i> A6 Sensitive Data</a> </li> <li><a href="/tutorial/a7"><i class="fa fa-wrench"></i> A7 Access Controls</a> </li> <li><a href="/tutorial/a8"><i class="fa fa-wrench"></i> A8 CSRF</a> </li> <li><a href="/tutorial/a9"><i class="fa fa-wrench"></i> A9 Insecure Components</a> </li> <li><a href="/tutorial/a10"><i class="fa fa-wrench"></i> A10 Redirects</a> </li> <li><a href="/tutorial/redos"><i class="fa"></i> ReDoS Attacks</a> </li> <li><a href="/tutorial/ssrf"><i class="fa"></i> SSRF</a> </li> </ul> <ul class="nav navbar-nav navbar-right navbar-user"> <li><a href="/login"><i class="fa fa-power-off"></i> Exit</a> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <h1>A1 - Injection <small></small> </h1> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="bs-example" style="margin-bottom: 40px;"> <span class="label label-danger">Exploitability: EASY</span> <span class="label label-warning">Prevalence: COMMON</span> <span class="label label-warning">Detectability: AVERAGE</span> <span class="label label-danger">Technical Impact: SEVERE</span> </div> </div> </div> <div class="row"> <div class="col-lg-12"> <div class="panel panel-info"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> Injection flaws occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization. </div> </div> <!-- <div class="panel panel-info"> <div class="panel-heading"> <h3 class="panel-title">Real World Attack Incident Examples</h3> </div> <div class="panel-body"> Screencast here ... </div> </div> --> </div> </div> <!-- accordions --> <div class="panel-group" id="accordion"> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne"> <i class="fa fa-chevron-down"></i>A1 - 1 Server Side JS Injection </a> </h4> </div> <div id="collapseOne" class="panel-collapse collapse in"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> When <code>eval()</code>, <code>setTimeout()</code>, <code>setInterval()</code>, <code>Function()</code>are used to process user provided inputs, it can be exploited by an attacker to inject and execute malicious JavaScript code on server. </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p> Web applications using the JavaScript <code>eval()</code>function to parse the incoming data without any type of input validation are vulnerable to this attack. An attacker can inject arbitrary JavaScript code to be executed on the server. Similarly <code>setTimeout()</code>, and <code>setInterval()</code>functions can take code in string format as a first argument causing same issues as <code>eval()</code>. </p> <p>This vulnerability can be very critical and damaging by allowing attacker to send various types of commands.</p> <p> <b>Denial of Service Attack:</b> </p> <iframe width="560" height="315" src="//www.youtube.com/embed/krOx9QWwcYw?rel=0" frameborder="0" allowfullscreen></iframe> <p> An effective denial-of-service attack can be executed simply by sending the commands below to <code>eval()</code>function: </p> <pre>while(1)</pre> <p> This input will cause the target server's event loop to use 100% of its processor time and unable to process any other incoming requests until process is restarted. </p> <p> An alternative DoS attack would be to simply exit or kill the running process: <pre>process.exit()</pre> or <pre>process.kill(process.pid) </pre> </p> <p> <b>File System Access</b> <br/> </p> <iframe width="560" height="315" src="//www.youtube.com/embed/Mr-Jh9bjSLo?rel=0" frameborder="0" allowfullscreen></iframe> <p> Another potential goal of an attacker might be to read the contents of files from the server. For example, following two commands list the contents of the current directory and parent directory respectively: </p> <p> <pre>res.end(require('fs').readdirSync('.').toString())</pre> <pre>res.end(require('fs').readdirSync('..').toString()) </pre> </p> <p> Once file names are obtained, an attacker can issue the command below to view the actual contents of a file: </p> <p> <pre>res.end(require('fs').readFileSync(filename))</pre> </p> <p> An attacker can further exploit this vulnerability by writing and executing harmful binary files using <code>fs</code>and <code>child_process</code>modules. </p> </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> To prevent server-side js injection attacks: <ul> <li>Validate user inputs on server side before processing</li> <li>Do not use <code>eval()</code>function to parse user inputs. Avoid using other commands with similar effect, such as <code>setTimeOut()</code>, <code>setInterval()</code>, and <code>Function()</code>. </li> <li> For parsing JSON input, instead of using <code>eval()</code>, use a safer alternative such as <code>JSON.parse()</code>. For type conversions use type related <code>parseXXX()</code>methods. </li> <li>Include <code>"use strict"</code>at the beginning of a function, which enables <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode"> strict mode </a>within the enclosing function scope.</li> </ul> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p>In <code>routes/contributions.js</code>, the <code>handleContributionsUpdate()</code>function insecurely uses <code>eval()</code>to convert user supplied contribution amounts to integer. <pre> // Insecure use of eval() to parse inputs var preTax = eval(req.body.preTax); var afterTax = eval(req.body.afterTax); var roth = eval(req.body.roth); </pre> This makes application vulnerable to SSJS attack. It can fixed simply by using <code>parseInt()</code>instead. <pre> //Fix for A1 -1 SSJS Injection attacks - uses alternate method to eval var preTax = parseInt(req.body.preTax); var afterTax = parseInt(req.body.afterTax); var roth = parseInt(req.body.roth); </pre> </p> <p>In addition, all functions begin with <code>use strict</code>pragma. </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Further Reading</h3> </div> <div class="panel-body"> <ul> <li><a target="_blank" href="https://media.blackhat.com/bh-us-11/Sullivan/BH_US_11_Sullivan_Server_Side_WP.pdf">“ServerSide JavaScript Injection: Attacking NoSQL and Node.js"</a> a whitepaper by Bryan Sullivan.</li> </ul> </div> </div> </div> </div> </div> <!-- /ssjs --> <!-- DB Injection --> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo"> <i class="fa fa-chevron-down"></i> A1 - 2 SQL and NoSQL Injection </a> </h4> </div> <div id="collapseTwo" class="panel-collapse"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> <p> SQL and NoSQL injections enable an attacker to inject code into the query that would be executed by the database. These flaws are introduced when software developers create dynamic database queries that include user supplied input. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p>Both SQL and NoSQL databases are vulnerable to injection attack. Here is an example of equivalent attack in both cases, where attacker manages to retrieve admin user's record without knowing password:</p> <h5>1. SQL Injection</h5> <p>Lets consider an example SQL statement used to authenticate the user with username and password</p> <pre>SELECT * FROM accounts WHERE username = '$username' AND password = '$password'</pre> <p>If this statement is not prepared or properly handled when constructed, an attacker may be able to supply <code>admin' --</code>in the username field to access the admin user's account bypassing the condition that checks for the password. The resultant SQL query would looks like:</p> <pre>SELECT * FROM accounts WHERE username = 'admin' -- AND password = ''</pre> <br/> <h5>2. NoSQL Injection</h5> <p>The equivalent of above query for NoSQL MongoDB database is:</p> <pre>db.accounts.find({username: username, password: password});</pre> <p>While here we are no longer dealing with query language, an attacker can still achieve the same results as SQL injection by supplying JSON input object as below:</p> <pre> { "username": "admin", "password": {$gt: ""} } </pre> <p>In MongoDB, <code>$gt</code>selects those documents where the value of the field is greater than (i.e. >) the specified value. Thus above statement compares password in database with empty string for greatness, which returns <code>true</code>.</p> <p>The same results can be achieved using other comparison operator such as <code>$ne</code>.</p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">SSJS Attack Mechanics</h3> </div> <div class="panel-body"> <p> Server-side JavaScript Injection (SSJS) is an attack where JavaScript code is injected and executed in a server component. MongoDB specifically, is vulnerable to this attack when queries are run without proper sanitization. </p> <h5>$where operator</h5> <p> MongoDB's <code>$where</code> operator performs JavaScript expression evaluation on the MongoDB server. If the user is able to inject direct code into such queries then such an attack can take place </p> <p> Lets consider an example query: </p> <pre> db.allocationsCollection.find({ $where: "this.userId == '" + parsedUserId + "' && " + "this.stocks > " + "'" + threshold + "'" }); </pre> <p> The code will match all documents which have a <code>userId</code> field as specified by <code>parsedUserId</code> and a <code>stocks</code> field as specified by <code>threshold</code>. The problem is that these parameters are not validated, filtered, or sanitised, and vulnerable to SSJS Injection. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> Here are some measures to prevent SQL / NoSQL injection attacks, or minimize impact if it happens: <ul> <li>Prepared Statements: For SQL calls, use prepared statements instead of building dynamic queries using string concatenation.</li> <li>Input Validation: Validate inputs to detect malicious values. For NoSQL databases, also validate input types against expected types</li> <li>Least Privilege: To minimize the potential damage of a successful injection attack, do not assign DBA or admin type access rights to your application accounts. Similarly minimize the privileges of the operating system account that the database process runs under.</li> </ul> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p><strong>Note: These vulnerabilities are not present when using an Atlas M0 cluster with NodeGoat.</strong></p> <p>The Allocations page of the demo application is vulnerable to NoSQL Injection. For example, set the stocks threshold filter to:</p> <pre>1'; return 1 == '1</pre> <p>This will retrieve allocations for all the users in the database.</p> <p>An attacker could also send the following input for the <code>threshold</code> field in the request's query, which will create a valid JavaScript expression and satisfy the <code> $where</code> query as well, resulting in a DoS attack on the MongoDB server: </p> <pre>http://localhost:4000/allocations/2?threshold=5';while(true){};' </pre> <p> You can also just drop the following into the Stocks Threshold input box: </p> <pre>';while(true){};'</pre> <p>For these vulnerabilities, bare minimum fixes can be found in <code>allocations.html</code> and <code>allocations-dao.js</code></p> </div> </div> </div> </div> </div> <!-- /NoSQL Injection --> <!-- Log Injection --> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree"> <i class="fa fa-chevron-down"></i> A1 - 3 Log Injection </a> </h4> </div> <div id="collapseThree" class="panel-collapse"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> <p> Log injection vulnerabilities enable an attacker to forge and tamper with an application's logs. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p>An attacker may craft a malicious request that may deliberately fail, which the application will log, and when attacker's user input is unsanitized, the payload is sent as-is to the logging facility. Vulnerabilities may vary depending on the logging facility:</p> <h5>1. Log Forging (CRLF) </h5> <p>Lets consider an example where an application logs a failed attempt to login to the system. A very common example for this is as follows: </p> <pre> var userName = req.body.userName; console.log('Error: attempt to login with invalid user: ', userName); </pre> <p>When user input is unsanitized and the output mechanism is an ordinary terminal stdout facility then the application will be vulnerable to CRLF injection, where an attacker can create a malicious payload as follows: <pre> curl http://localhost:4000/login -X POST --data 'userName=vyva%0aError: alex moldovan failed $1,000,000 transaction&password=Admin_123&_csrf=' </pre> Where the <code>userName</code> parameter is encoding in the request the LF symbol which will result in a new line to begin. Resulting log output will look as follows: <pre> Error: attempt to login with invalid user: vyva Error: alex moldovan failed $1,000,000 transaction </pre> <br/> <h5>2. Log Injection Escalation </h5> <p> An attacker may craft malicious input in hope of an escalated attack where the target isn't the logs themselves, but rather the actual logging system. For example, if an application has a back-office web app that manages viewing and tracking the logs, then an attacker may send an XSS payload into the log, which may not result in log forging on the log itself, but when viewed by a system administrator on the log viewing web app then it may compromise it and result in XSS injection that if the logs app is vulnerable. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> As always when dealing with user input: <ul> <li> Do not allow user input into logs </li> <li> Encode to proper context, or sanitize user input </li> </ul> Encoding example: <pre> // Step 1: Require a module that supports encoding var ESAPI = require('node-esapi'); // - Step 2: Encode the user input that will be logged in the correct context // following are a few examples: console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForHTML(userName)); console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForJavaScript(userName)); console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForURL(userName)); </pre> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p>For the above Log Injection vulnerability, example and fix can be found at <code>routes/session.js</code></p> </div> </div> </div> </div> </div> <!-- /Log Injection --> </div> <!-- end accordions --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <script src="../vendor/jquery.min.js"></script> <script src="../vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/login |
| Method | POST |
| Parameter | x-frame-options |
| Attack | |
| Evidence | |
| Request Header - size: 697 bytes. |
POST http://jenkins_docker-compose_application_web_1:4000/login HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Content-Type: application/x-www-form-urlencoded Content-Length: 34 Origin: http://jenkins_docker-compose_application_web_1:4000 Connection: keep-alive Cookie: connect.sid=s%3AyGMSRGNYEF-6z61RLvRrrBNTAh_dtQGn.53w2hKRBLZfOMBxxohiuNfCoghCrZtv7qOJEujRc5IM Upgrade-Insecure-Requests: 1 |
| Request Body - size: 34 bytes. |
userName=HhyVAgNS&password=&_csrf=
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 7514 ETag: W/"1d5a-vBvXIMawvps2XiuMx1Ih4luZS3I" Date: Mon, 29 Jan 2024 16:33:48 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 7,514 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="OWASP NodeGoat Project: Insecure App"> <meta name="version" content="v1.2"> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="https://www.owasp.org/index.php/Projects/OWASP_Node_js_Goat_Project">OWASP Node Goat Project</a> </div> <!-- Nav Links--> <div class="collapse navbar-collapse navbar-ex1-collapse"> <!-- top nav --> <ul class="nav navbar-nav navbar-right navbar-user"> <li class="dropdown user-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" style="font-size: larger"><i class="fa fa-info-circle"></i></a> <ul class="dropdown-menu alert-dropdown" style="min-width: 350px; padding: 10px"> <li> <p> The OWASP Node Goat is an educational Node.js web application vulnerable to the <a target="_blank" href="https://www.owasp.org/index.php/Top_10_2013-Top_10"> OWASP Top 10</a> risks.</p> <p>It is intended to show how each of these vulnerabilities can manifest in a Node.js specific way, and provides the subsequent mitigation for each with source code examples. </p> <p>To start hacking the application, login using the form below, or access the tutorial guide to know more.</p> </li> <li class="divider"></li> <li style="text-align: right"> <i class="fa fa-tag"> </i> v1.2 </li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div style="text-align: center; padding: 30px"> <img src="/images/owasplogo.png" height="80px"> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-4"></div> <div class="col-lg-4"> <div class="panel panel-info"> <div class="panel-heading" style="text-align: center"> <a href="/tutorial" target="_blank"> <b><span class="fa fa-book"></span> Tutorial Guide:</b> Learn OWASP Top 10 </a> </div> </div> <div class="panel panel-default"> <div class="panel-heading" style="text-align: center"> <span style="font-size: x-large"> <span class="fa fa-bullseye"></span>Retire<b>Easy</b> </span> <br /> <span style="font-size: medium">Employee Retirement Savings Management</span> <br /> <br /> </div> <div class="panel-body"> <div class="alert alert-dismissable alert-danger"> <button type="button" class="close" data-dismiss="alert">×</button> Invalid username </div> <form method="post" role="form" method="post" id="loginform"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" name="userName" value="HhyVAgNS" placeholder="Enter User Name"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter Password"> </div> <input type="hidden" name="_csrf" value="" /> <div class="row"> <div class="col-lg-4"><a href="/signup">New user? Sign Up</a> </div> <div class="col-lg-5"></div> <div class="col-lg-3"> <button type="submit" class="btn btn-danger">Submit</button> </div> </div> </form> </div> </div> </div> <div class="col-lg-4"></div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> <!-- /.row --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> <script type="application/javascript"> const areCookiesEnabled = () => { const cookieEnabled = navigator.cookieEnabled; // When cookieEnabled flag is present and false then cookies are disabled. if (!cookieEnabled) return false; // try to set a test cookie if we can't see any cookies and we're using // either a browser that doesn't support navigator.cookieEnabled // or IE (which always returns true for navigator.cookieEnabled) if (!document.cookie && cookieEnabled === null) { document.cookie = "testcookie=1"; if (!document.cookie) return false; document.cookie = "testcookie=; expires=" + new Date(0).toUTCString(); } return true; } $(document).ready(() => { if (!areCookiesEnabled()) { $("#page-wrapper").prepend("<div class=\"row\"><div class=\"col-lg-12\"><div class=\"alert alert-danger\">Cookies are not enabled on your browser. Please enable cookies in your browser preferences to continue.</div></div></div>"); } }); </script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/signup |
| Method | POST |
| Parameter | x-frame-options |
| Attack | |
| Evidence | |
| Request Header - size: 701 bytes. |
POST http://jenkins_docker-compose_application_web_1:4000/signup HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/signup Content-Type: application/x-www-form-urlencoded Content-Length: 86 Origin: http://jenkins_docker-compose_application_web_1:4000 Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg Upgrade-Insecure-Requests: 1 |
| Request Body - size: 86 bytes. |
userName=ECeNuwfl&firstName=zAuRhWJS&lastName=GuQMUShW&password=&verify=&email=&_csrf=
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 4999 ETag: W/"1387-k/xYlSuNY0T8Jt7I4fy0VJVIBXA" Date: Mon, 29 Jan 2024 16:33:58 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 4,999 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <!-- Add custom CSS here --> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="/">OWASP Node Goat Project</a> </div> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div class="well well-sm"> Already a user? <a href="/login">Login</a> <p> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="alert alert-dismissable alert-danger"> <button type="button" class="close" data-dismiss="alert">×</button> <p>Password must be 8 to 18 characters including numbers, lowercase and uppercase letters.</p> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Enter sign up information</h3> </div> <div class="panel-body"> <form method="post" role="form" method="post"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" value="ECeNuwfl" name="userName" placeholder="Enter user name"> </div> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" value="" name="firstName" placeholder="Enter first name"> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" value="" name="lastName" placeholder="Enter last name"> </div> <div class="form-group"> <label for="lastname">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Verify Password</label> <input type="password" class="form-control" id="verify" name="verify" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Email (Optional)</label> <input type="email" class="form-control" id="email" name="email" value="" placeholder="Enter email"> </div> <input type="hidden" name="_csrf" value=""></input> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| Instances | 6 |
| Solution |
Modern Web browsers support the Content-Security-Policy and X-Frame-Options HTTP headers. Ensure one of them is set on all web pages returned by your site/app.
If you expect the page to be framed only by pages on your server (e.g. it's part of a FRAMESET) then you'll want to use SAMEORIGIN, otherwise if you never expect the page to be framed, you should use DENY. Alternatively consider implementing Content Security Policy's "frame-ancestors" directive.
|
| Reference | https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options |
| Tags |
OWASP_2021_A05
WSTG-v42-CLNT-09 OWASP_2017_A06 |
| CWE Id | 1021 |
| WASC Id | 15 |
| Plugin Id | 10020 |
|
Medium |
Vulnerable JS Library |
|---|---|
| Description |
The identified library jquery, version 1.10.2 is vulnerable.
|
| URL | http://jenkins_docker-compose_application_web_1:4000/vendor/bootstrap/bootstrap.js |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | * Bootstrap v3.0.0 |
| Request Header - size: 479 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/vendor/bootstrap/bootstrap.js HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: */* Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 332 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Accept-Ranges: bytes Cache-Control: public, max-age=0 Last-Modified: Wed, 03 Jan 2024 18:30:11 GMT ETag: W/"6d09-18cd09715cf" Content-Type: application/javascript; charset=UTF-8 Content-Length: 27913 Date: Mon, 29 Jan 2024 16:33:31 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 27,913 bytes. |
/*!
* Bootstrap v3.0.0 * * Copyright 2013 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. */ +function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function f(){e.trigger("closed.bs.alert").remove()}var c=a(this),d=c.attr("data-target");d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));var e=a(d);b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.trigger(b=a.Event("close.bs.alert"));if(b.isDefaultPrevented())return;e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.one(a.support.transition.end,f).emulateTransitionEnd(150):f()};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");b.prop("type")==="radio"&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f=typeof c=="object"&&c;e||d.data("bs.button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,this.options.pause=="hover"&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();if(b>this.$items.length-1||b<0)return;return this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){if(this.sliding)return;return this.slide("next")},b.prototype.prev=function(){if(this.sliding)return;return this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(e.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")}));if(a.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(j);if(j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{this.$element.trigger(j);if(j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),typeof c=="object"&&c),g=typeof c=="string"?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),typeof c=="number"?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),c.data()),g=c.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=c.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(window.jQuery),+function(a){function e(){a(b).remove(),a(c).each(function(b){var c=f(a(this));if(!c.hasClass("open"))return;c.trigger(b=a.Event("hide.bs.dropdown"));if(b.isDefaultPrevented())return;c.removeClass("open").trigger("hidden.bs.dropdown")})}function f(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}"use strict";var b=".dropdown-backdrop",c="[data-toggle=dropdown]",d=function(b){var c=a(b).on("click.bs.dropdown",this.toggle)};d.prototype.toggle=function(b){var c=a(this);if(c.is(".disabled, :disabled"))return;var d=f(c),g=d.hasClass("open");e();if(!g){"ontouchstart"in document.documentElement&&!d.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",e),d.trigger(b=a.Event("show.bs.dropdown"));if(b.isDefaultPrevented())return;d.toggleClass("open").trigger("shown.bs.dropdown"),c.focus()}return!1},d.prototype.keydown=function(b){if(!/(38|40|27)/.test(b.keyCode))return;var d=a(this);b.preventDefault(),b.stopPropagation();if(d.is(".disabled, :disabled"))return;var e=f(d),g=e.hasClass("open");if(!g||g&&b.keyCode==27)return b.which==27&&e.find(c).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",e);if(!h.length)return;var i=h.index(h.filter(":focus"));b.keyCode==38&&i>0&&i--,b.keyCode==40&&i<h.length-1&&i++,~i||(i=0),h.eq(i).focus()};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),e=c.data("dropdown");e||c.data("dropdown",e=new d(this)),typeof b=="string"&&e[b].call(c)})},a.fn.dropdown.Constructor=d,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",e).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",c,d.prototype.toggle).on("keydown.bs.dropdown.data-api",c+", [role=menu]",d.prototype.keydown)}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.load(this.options.remote)};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d);if(this.isShown||d.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.$element.on("click.dismiss.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show(),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)})},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b);if(!this.isShown||b.isDefaultPrevented())return;this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal()},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]!==a.target&&!this.$element.has(a.target).length&&this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){a.which==27&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('<div class="modal-backdrop '+d+'" />').appendTo(document.body),this.$element.on("click.dismiss.modal",a.proxy(function(a){if(a.target!==a.currentTarget)return;this.options.backdrop=="static"?this.$element[0].focus.call(this.$element[0]):this.hide.call(this)},this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!b)return;e?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),typeof c=="object"&&c);f||e.data("bs.modal",f=new b(this,g)),typeof c=="string"?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(window.jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);var e=this.options.trigger.split(" ");for(var f=e.length;f--;){var g=e[f];if(g=="click")this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if(g!="manual"){var h=g=="hover"?"mouseenter":"focus",i=g=="hover"?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&typeof b.delay=="number"&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(c.timeout),c.hoverState="in";if(!c.options.delay||!c.options.delay.show)return c.show();c.timeout=setTimeout(function(){c.hoverState=="in"&&c.show()},c.options.delay.show)},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(c.timeout),c.hoverState="out";if(!c.options.delay||!c.options.delay.hide)return c.hide();c.timeout=setTimeout(function(){c.hoverState=="out"&&c.hide()},c.options.delay.hide)},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);if(b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d=typeof this.options.placement=="function"?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m=this.options.container=="body"?window.innerWidth:j.outerWidth(),n=this.options.container=="body"?window.innerHeight:j.outerHeight(),o=this.options.container=="body"?0:j.offset().left;d=d=="bottom"&&g.top+g.height+i-l>n?"top":d=="top"&&g.top-l-i<0?"bottom":d=="right"&&g.right+h>m?"left":d=="left"&&g.left-h<o?"right":d,c.removeClass(k).addClass(d)}var p=this.getCalculatedOffset(d,g,h,i);this.applyPlacement(p,d),this.$element.trigger("shown.bs."+this.type)}},b.prototype.applyPlacement=function(a,b){var c,d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),a.top=a.top+g,a.left=a.left+h,d.offset(a).addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;b=="top"&&j!=f&&(c=!0,a.top=a.top+f-j);if(/bottom|top/.test(b)){var k=0;a.left<0&&(k=a.left*-2,a.left=0,d.offset(a),i=d[0].offsetWidth,j=d[0].offsetHeight),this.replaceArrow(k-e+i,i,"left")}else this.replaceArrow(j-f,j,"top");c&&d.offset(a)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function e(){b.hoverState!="in"&&c.detach()}var b=this,c=this.tip(),d=a.Event("hide.bs."+this.type);this.$element.trigger(d);if(d.isDefaultPrevented())return;return c.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?c.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),this.$element.trigger("hidden.bs."+this.type),this},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||typeof a.attr("data-original-title")!="string")&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},typeof b.getBoundingClientRect=="function"?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return a=="bottom"?{top:b.top+b.height,left:b.left+b.width/2-c/2}:a=="top"?{top:b.top-d,left:b.left+b.width/2-c/2}:a=="left"?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||(typeof c.title=="function"?c.title.call(b[0]):c.title),a},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f=typeof c=="object"&&c;e||d.data("bs.tooltip",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(window.jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||(typeof b.content=="function"?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f=typeof c=="object"&&c;e||d.data("bs.popover",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target");d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));if(b.parent("li").hasClass("active"))return;var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});b.trigger(f);if(f.isDefaultPrevented())return;var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})},b.prototype.activate=function(b,c,d){function g(){e.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),f?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var e=c.find("> .active"),f=d&&a.support.transition&&e.hasClass("fade");f?e.one(a.support.transition.end,g).emulateTransitionEnd(150):g(),e.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),typeof c=="string"&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;typeof f!="object"&&(h=g=f),typeof g=="function"&&(g=f.top()),typeof h=="function"&&(h=f.bottom());var i=this.unpin!=null&&d+this.unpin<=e.top?!1:h!=null&&e.top+this.$element.height()>=c-h?"bottom":g!=null&&d<=g?"top":!1;if(this.affixed===i)return;this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin=i=="bottom"?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),i=="bottom"&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()})};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f=typeof c=="object"&&c;e||d.data("bs.affix",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(this.transitioning||this.$element.hasClass("in"))return;var b=a.Event("show.bs.collapse");this.$element.trigger(b);if(b.isDefaultPrevented())return;var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])},b.prototype.hide=function(){if(this.transitioning||!this.$element.hasClass("in"))return;var b=a.Event("hide.bs.collapse");this.$element.trigger(b);if(b.isDefaultPrevented())return;var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};if(!a.support.transition)return d.call(this);this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350)},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),typeof c=="object"&&c);e||d.data("bs.collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":c.data(),i=c.attr("data-parent"),j=i&&a(i);if(!g||!g.transitioning)j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(c).addClass("collapsed"),c[f.hasClass("in")?"addClass":"removeClass"]("collapsed");f.collapse(h)})}(window.jQuery),+function(a){function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}"use strict",b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this,d=this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a=this.$scrollElement.scrollTop()+this.options.offset,b=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,c=b-this.$scrollElement.height(),d=this.offsets,e=this.targets,f=this.activeTarget,g;if(a>=c)return f!=(g=e.last()[0])&&this.activate(g);for(g=d.length;g--;)f!=e[g]&&a>=d[g]&&(!d[g+1]||a<=d[g+1])&&this.activate(e[g])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f=typeof c=="object"&&c;e||d.data("bs.scrollspy",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),+function(a){function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(a.style[c]!==undefined)return{end:b[c]}}"use strict",a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(window.jQuery) |
| URL | http://jenkins_docker-compose_application_web_1:4000/vendor/jquery.min.js |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | /*! jQuery v1.10.2 |
| Request Header - size: 470 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/vendor/jquery.min.js HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: */* Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 333 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Accept-Ranges: bytes Cache-Control: public, max-age=0 Last-Modified: Wed, 03 Jan 2024 18:30:11 GMT ETag: W/"16bab-18cd09715d3" Content-Type: application/javascript; charset=UTF-8 Content-Length: 93099 Date: Mon, 29 Jan 2024 16:33:31 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 93,099 bytes. |
/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license
//@ sourceMappingURL=jquery.min.map */ (function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="<div class='a'></div><div class='a i'></div>",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav></:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t }({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Ct=/^(?:checkbox|radio)$/i,Nt=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:x.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=un(e,t),Pt.detach()),Gt[e]=n),n}function un(e,t){var n=x(t.createElement(e)).appendTo(t.body),r=x.css(n[0],"display");return n.remove(),r}x.each(["height","width"],function(e,n){x.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(x.css(e,"display"))?x.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,i),i):0)}}}),x.support.opacity||(x.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=x.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===x.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),x(function(){x.support.reliableMarginRight||(x.cssHooks.marginRight={get:function(e,n){return n?x.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!x.support.pixelPosition&&x.fn.position&&x.each(["top","left"],function(e,n){x.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?x(e).position()[n]+"px":r):t}}})}),x.expr&&x.expr.filters&&(x.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!x.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||x.css(e,"display"))},x.expr.filters.visible=function(e){return!x.expr.filters.hidden(e)}),x.each({margin:"",padding:"",border:"Width"},function(e,t){x.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(x.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;x.fn.extend({serialize:function(){return x.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=x.prop(this,"elements");return e?x.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!x(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Ct.test(e))}).map(function(e,t){var n=x(this).val();return null==n?null:x.isArray(n)?x.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),x.param=function(e,n){var r,i=[],o=function(e,t){t=x.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=x.ajaxSettings&&x.ajaxSettings.traditional),x.isArray(e)||e.jquery&&!x.isPlainObject(e))x.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(x.isArray(t))x.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==x.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}x.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){x.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),x.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}});var mn,yn,vn=x.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Cn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Nn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=x.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=o.href}catch(Ln){yn=a.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(T)||[];if(x.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(l){var u;return o[l]=!0,x.each(e[l]||[],function(e,l){var c=l(n,r,i);return"string"!=typeof c||a||o[c]?a?!(u=c):t:(n.dataTypes.unshift(c),s(c),!1)}),u}return s(n.dataTypes[0])||!o["*"]&&s("*")}function _n(e,n){var r,i,o=x.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&x.extend(!0,e,r),e}x.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,l=e.indexOf(" ");return l>=0&&(i=e.slice(l,e.length),e=e.slice(0,l)),x.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&x.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?x("<div>").append(x.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},x.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){x.fn[t]=function(e){return this.on(t,e)}}),x.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Cn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":x.parseJSON,"text xml":x.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?_n(_n(e,x.ajaxSettings),t):_n(x.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,l,u,c,p=x.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?x(f):x.event,h=x.Deferred(),g=x.Callbacks("once memory"),m=p.statusCode||{},y={},v={},b=0,w="canceled",C={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return b||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>b)for(t in e)m[t]=[m[t],e[t]];else C.always(e[C.status]);return this},abort:function(e){var t=e||w;return u&&u.abort(t),k(0,t),this}};if(h.promise(C).complete=g.add,C.success=C.done,C.error=C.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=x.trim(p.dataType||"*").toLowerCase().match(T)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?"80":"443"))===(mn[3]||("http:"===mn[1]?"80":"443")))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=x.param(p.data,p.traditional)),qn(An,p,n,C),2===b)return C;l=p.global,l&&0===x.active++&&x.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Nn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(x.lastModified[o]&&C.setRequestHeader("If-Modified-Since",x.lastModified[o]),x.etag[o]&&C.setRequestHeader("If-None-Match",x.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&C.setRequestHeader("Content-Type",p.contentType),C.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)C.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,C,p)===!1||2===b))return C.abort();w="abort";for(i in{success:1,error:1,complete:1})C[i](p[i]);if(u=qn(jn,p,n,C)){C.readyState=1,l&&d.trigger("ajaxSend",[C,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){C.abort("timeout")},p.timeout));try{b=1,u.send(y,k)}catch(N){if(!(2>b))throw N;k(-1,N)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,N=n;2!==b&&(b=2,s&&clearTimeout(s),u=t,a=i||"",C.readyState=e>0?4:0,c=e>=200&&300>e||304===e,r&&(w=Mn(p,C,r)),w=On(p,w,C,c),c?(p.ifModified&&(T=C.getResponseHeader("Last-Modified"),T&&(x.lastModified[o]=T),T=C.getResponseHeader("etag"),T&&(x.etag[o]=T)),204===e||"HEAD"===p.type?N="nocontent":304===e?N="notmodified":(N=w.state,y=w.data,v=w.error,c=!v)):(v=N,(e||!N)&&(N="error",0>e&&(e=0))),C.status=e,C.statusText=(n||N)+"",c?h.resolveWith(f,[y,N,C]):h.rejectWith(f,[C,N,v]),C.statusCode(m),m=t,l&&d.trigger(c?"ajaxSuccess":"ajaxError",[C,p,c?y:v]),g.fireWith(f,[C,N]),l&&(d.trigger("ajaxComplete",[C,p]),--x.active||x.event.trigger("ajaxStop")))}return C},getJSON:function(e,t,n){return x.get(e,t,n,"json")},getScript:function(e,n){return x.get(e,t,n,"script")}}),x.each(["get","post"],function(e,n){x[n]=function(e,r,i,o){return x.isFunction(r)&&(o=o||i,i=r,r=t),x.ajax({url:e,type:n,dataType:o,data:r,success:i})}});function Mn(e,n,r){var i,o,a,s,l=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in l)if(l[s]&&l[s].test(o)){u.unshift(s);break}if(u[0]in r)a=u[0];else{for(s in r){if(!u[0]||e.converters[s+" "+u[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==u[0]&&u.unshift(a),r[a]):t}function On(e,t,n,r){var i,o,a,s,l,u={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)u[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if("*"===o)o=l;else if("*"!==l&&l!==o){if(a=u[l+" "+o]||u["* "+o],!a)for(i in u)if(s=i.split(" "),s[1]===o&&(a=u[l+" "+s[0]]||u["* "+s[0]])){a===!0?a=u[i]:u[i]!==!0&&(o=s[0],c.unshift(s[1]));break}if(a!==!0)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(p){return{state:"parsererror",error:a?p:"No conversion from "+l+" to "+o}}}return{state:"success",data:t}}x.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return x.globalEval(e),e}}}),x.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),x.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=a.head||x("head")[0]||a.documentElement;return{send:function(t,i){n=a.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var Fn=[],Bn=/(=)\?(?=&|$)|\?\?/;x.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Fn.pop()||x.expando+"_"+vn++;return this[e]=!0,e}}),x.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,l=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return l||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=x.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,l?n[l]=n[l].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||x.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,Fn.push(o)),s&&x.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}x.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=x.ajaxSettings.xhr(),x.support.cors=!!Rn&&"withCredentials"in Rn,Rn=x.support.ajax=!!Rn,Rn&&x.ajaxTransport(function(n){if(!n.crossDomain||x.support.cors){var r;return{send:function(i,o){var a,s,l=n.xhr();if(n.username?l.open(n.type,n.url,n.async,n.username,n.password):l.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)l[s]=n.xhrFields[s];n.mimeType&&l.overrideMimeType&&l.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)l.setRequestHeader(s,i[s])}catch(u){}l.send(n.hasContent&&n.data||null),r=function(e,i){var s,u,c,p;try{if(r&&(i||4===l.readyState))if(r=t,a&&(l.onreadystatechange=x.noop,$n&&delete Pn[a]),i)4!==l.readyState&&l.abort();else{p={},s=l.status,u=l.getAllResponseHeaders(),"string"==typeof l.responseText&&(p.text=l.responseText);try{c=l.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,u)},n.async?4===l.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},x(e).unload($n)),Pn[a]=r),l.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+w+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=Yn.exec(t),o=i&&i[3]||(x.cssNumber[e]?"":"px"),a=(x.cssNumber[e]||"px"!==o&&+r)&&Yn.exec(x.css(n.elem,e)),s=1,l=20;if(a&&a[3]!==o){o=o||a[3],i=i||[],a=+r||1;do s=s||".5",a/=s,x.style(n.elem,e,a+o);while(s!==(s=n.cur()/r)&&1!==s&&--l)}return i&&(a=n.start=+a||+r||0,n.unit=o,n.end=i[1]?a+(i[1]+1)*i[2]:+i[2]),n}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=x.now()}function Zn(e,t,n){var r,i=(Qn[t]||[]).concat(Qn["*"]),o=0,a=i.length;for(;a>o;o++)if(r=i[o].call(n,t,e))return r}function er(e,t,n){var r,i,o=0,a=Gn.length,s=x.Deferred().always(function(){delete l.elem}),l=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,u.startTime+u.duration-t),r=n/u.duration||0,o=1-r,a=0,l=u.tweens.length;for(;l>a;a++)u.tweens[a].run(o);return s.notifyWith(e,[u,o,n]),1>o&&l?n:(s.resolveWith(e,[u]),!1)},u=s.promise({elem:e,props:x.extend({},t),opts:x.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=x.Tween(e,u.opts,t,n,u.opts.specialEasing[t]||u.opts.easing);return u.tweens.push(r),r},stop:function(t){var n=0,r=t?u.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)u.tweens[n].run(1);return t?s.resolveWith(e,[u,t]):s.rejectWith(e,[u,t]),this}}),c=u.props;for(tr(c,u.opts.specialEasing);a>o;o++)if(r=Gn[o].call(u,e,c,u.opts))return r;return x.map(c,Zn,u),x.isFunction(u.opts.start)&&u.opts.start.call(e,u),x.fx.timer(x.extend(l,{elem:e,anim:u,queue:u.opts.queue})),u.progress(u.opts.progress).done(u.opts.done,u.opts.complete).fail(u.opts.fail).always(u.opts.always)}function tr(e,t){var n,r,i,o,a;for(n in e)if(r=x.camelCase(n),i=t[r],o=e[n],x.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=x.cssHooks[r],a&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}x.Animation=x.extend(er,{tweener:function(e,t){x.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,l,u=this,c={},p=e.style,f=e.nodeType&&nn(e),d=x._data(e,"fxshow");n.queue||(s=x._queueHooks(e,"fx"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,u.always(function(){u.always(function(){s.unqueued--,x.queue(e,"fx").length||s.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],"inline"===x.css(e,"display")&&"none"===x.css(e,"float")&&(x.support.inlineBlockNeedsLayout&&"inline"!==ln(e.nodeName)?p.zoom=1:p.display="inline-block")),n.overflow&&(p.overflow="hidden",x.support.shrinkWrapBlocks||u.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],Vn.exec(i)){if(delete t[r],o=o||"toggle"===i,i===(f?"hide":"show"))continue;c[r]=d&&d[r]||x.style(e,r)}if(!x.isEmptyObject(c)){d?"hidden"in d&&(f=d.hidden):d=x._data(e,"fxshow",{}),o&&(d.hidden=!f),f?x(e).show():u.done(function(){x(e).hide()}),u.done(function(){var t;x._removeData(e,"fxshow");for(t in c)x.style(e,t,c[t])});for(r in c)a=Zn(f?d[r]:0,r,u),r in d||(d[r]=a.start,f&&(a.end=a.start,a.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}x.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(x.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?x.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=x.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){x.fx.step[e.prop]?x.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[x.cssProps[e.prop]]||x.cssHooks[e.prop])?x.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},x.each(["toggle","show","hide"],function(e,t){var n=x.fn[t];x.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),x.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=x.isEmptyObject(e),o=x.speed(t,n,r),a=function(){var t=er(this,x.extend({},e),o);(i||x._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=x.timers,a=x._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&x.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=x._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=x.timers,a=r?r.length:0;for(n.finish=!0,x.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}x.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){x.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),x.speed=function(e,t,n){var r=e&&"object"==typeof e?x.extend({},e):{complete:n||!n&&t||x.isFunction(e)&&e,duration:e,easing:n&&t||t&&!x.isFunction(t)&&t};return r.duration=x.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in x.fx.speeds?x.fx.speeds[r.duration]:x.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){x.isFunction(r.old)&&r.old.call(this),r.queue&&x.dequeue(this,r.queue)},r},x.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},x.timers=[],x.fx=rr.prototype.init,x.fx.tick=function(){var e,n=x.timers,r=0;for(Xn=x.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||x.fx.stop(),Xn=t},x.fx.timer=function(e){e()&&x.timers.push(e)&&x.fx.start()},x.fx.interval=13,x.fx.start=function(){Un||(Un=setInterval(x.fx.tick,x.fx.interval))},x.fx.stop=function(){clearInterval(Un),Un=null},x.fx.speeds={slow:600,fast:200,_default:400},x.fx.step={},x.expr&&x.expr.filters&&(x.expr.filters.animated=function(e){return x.grep(x.timers,function(t){return e===t.elem}).length}),x.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){x.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,x.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},x.offset={setOffset:function(e,t,n){var r=x.css(e,"position");"static"===r&&(e.style.position="relative");var i=x(e),o=i.offset(),a=x.css(e,"top"),s=x.css(e,"left"),l=("absolute"===r||"fixed"===r)&&x.inArray("auto",[a,s])>-1,u={},c={},p,f;l?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),x.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(u.top=t.top-o.top+p),null!=t.left&&(u.left=t.left-o.left+f),"using"in t?t.using.call(e,u):i.css(u)}},x.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===x.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),x.nodeName(e[0],"html")||(n=e.offset()),n.top+=x.css(e[0],"borderTopWidth",!0),n.left+=x.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-x.css(r,"marginTop",!0),left:t.left-n.left-x.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||s;while(e&&!x.nodeName(e,"html")&&"static"===x.css(e,"position"))e=e.offsetParent;return e||s})}}),x.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);x.fn[e]=function(i){return x.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?x(a).scrollLeft():o,r?o:x(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return x.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}x.each({Height:"height",Width:"width"},function(e,n){x.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){x.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return x.access(this,function(n,r,i){var o;return x.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?x.css(n,r,s):x.style(n,r,i,s)},n,a?i:t,a,null)}})}),x.fn.size=function(){return this.length},x.fn.andSelf=x.fn.addBack,"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=x:(e.jQuery=e.$=x,"function"==typeof define&&define.amd&&define("jquery",[],function(){return x}))})(window); |
| Instances | 2 |
| Solution |
Please upgrade to the latest version of jquery.
|
| Reference |
https://github.com/jquery/jquery/issues/2432
http://blog.jquery.com/2016/01/08/jquery-2-2-and-1-12-released/ http://research.insecurelabs.org/jquery/test/ https://blog.jquery.com/2019/04/10/jquery-3-4-0-released/ https://nvd.nist.gov/vuln/detail/CVE-2019-11358 https://github.com/advisories/GHSA-rmxg-73gg-4p98 https://nvd.nist.gov/vuln/detail/CVE-2015-9251 https://github.com/jquery/jquery/commit/753d591aea698e57d6db58c9f722cd0808619b1b https://bugs.jquery.com/ticket/11974 https://github.com/jquery/jquery.com/issues/162 https://blog.jquery.com/2020/04/10/jquery-3-5-0-released/ |
| Tags |
CVE-2020-11023
OWASP_2017_A09 CVE-2020-11022 OWASP_2021_A06 CVE-2015-9251 CVE-2019-11358 |
| CWE Id | 829 |
| WASC Id | |
| Plugin Id | 10003 |
|
Low |
Cookie without SameSite Attribute |
|---|---|
| Description |
A cookie has been set without the SameSite attribute, which means that the cookie can be sent as a result of a 'cross-site' request. The SameSite attribute is an effective counter measure to cross-site request forgery, cross-site script inclusion, and timing attacks.
|
| URL | http://jenkins_docker-compose_application_web_1:4000 |
| Method | GET |
| Parameter | connect.sid |
| Attack | |
| Evidence | set-cookie: connect.sid |
| Request Header - size: 179 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000 HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 348 bytes. |
HTTP/1.1 302 Found
X-Powered-By: Express Location: /login Vary: Accept Content-Type: text/plain; charset=utf-8 Content-Length: 28 set-cookie: connect.sid=s%3A2AoTPOmAOJtx2rXevPFTWfOgR8YGCZcc.bdYKd173c5UXsZzxlkfnIp%2FopQMrKHCQ2m3ggq7R2I8; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 28 bytes. |
Found. Redirecting to /login
|
| URL | http://jenkins_docker-compose_application_web_1:4000/ |
| Method | GET |
| Parameter | connect.sid |
| Attack | |
| Evidence | set-cookie: connect.sid |
| Request Header - size: 389 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/ HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 347 bytes. |
HTTP/1.1 302 Found
X-Powered-By: Express Location: /login Vary: Accept Content-Type: text/html; charset=utf-8 Content-Length: 56 set-cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:31 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 56 bytes. |
<p>Found. Redirecting to <a href="/login">/login</a></p>
|
| URL | http://jenkins_docker-compose_application_web_1:4000/.git/index |
| Method | GET |
| Parameter | connect.sid |
| Attack | |
| Evidence | set-cookie: connect.sid |
| Request Header - size: 190 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/.git/index HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 149 set-cookie: connect.sid=s%3AwqnsNnm0JNFr_c-ILLR7CjdG_uYo4VVW.cytWnLVcvPGOUZGePLI29wnKDcy1OW5%2B892M9AdtZFA; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 149 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /.git/index</pre> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/.svn/entries |
| Method | GET |
| Parameter | connect.sid |
| Attack | |
| Evidence | set-cookie: connect.sid |
| Request Header - size: 192 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/.svn/entries HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 151 set-cookie: connect.sid=s%3AjqDNMm6bCo9hIi4k-zSL1pEgKROsV3T2.QSVBq3yrtKUDHQC9%2FBsCW1JAc24P7RopxS7EnSiFTqA; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 151 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /.svn/entries</pre> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/.svn/wc.db |
| Method | GET |
| Parameter | connect.sid |
| Attack | |
| Evidence | set-cookie: connect.sid |
| Request Header - size: 190 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/.svn/wc.db HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 149 set-cookie: connect.sid=s%3Asv3hkzV3_ZpgbbMGSiyiA7G3ZgnCwyMt.hhEWpjJazSBDCxwMLxvQhhRLtPw%2Fsa2BSVPotWkO4KU; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 149 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /.svn/wc.db</pre> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/robots.txt |
| Method | GET |
| Parameter | connect.sid |
| Attack | |
| Evidence | set-cookie: connect.sid |
| Request Header - size: 190 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/robots.txt HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 149 set-cookie: connect.sid=s%3Ar4tgfCP6lvWxc8TFxe_odDtmgrPbmY4o.uLijHm0LWLpf9J92CTUdxM7UMbXX2Nvq6KJK%2FqEzGeQ; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 149 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /robots.txt</pre> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/sitemap.xml |
| Method | GET |
| Parameter | connect.sid |
| Attack | |
| Evidence | set-cookie: connect.sid |
| Request Header - size: 191 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/sitemap.xml HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 150 set-cookie: connect.sid=s%3A5evrs8D1vchX94X4CB-rok2Y6wuJEGXy.MB31%2BtYmIy1LskkHviWKPS7nQdX9n4DogB2v0z1lNIM; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 150 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /sitemap.xml</pre> </body> </html> |
| Instances | 7 |
| Solution |
Ensure that the SameSite attribute is set to either 'lax' or ideally 'strict' for all cookies.
|
| Reference | https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site |
| Tags |
OWASP_2021_A01
WSTG-v42-SESS-02 OWASP_2017_A05 |
| CWE Id | 1275 |
| WASC Id | 13 |
| Plugin Id | 10054 |
|
Low |
Cross-Domain JavaScript Source File Inclusion |
|---|---|
| Description |
The page includes one or more script files from a third-party domain.
|
| URL | http://jenkins_docker-compose_application_web_1:4000 |
| Method | GET |
| Parameter | http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js |
| Attack | |
| Evidence | <script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> |
| Request Header - size: 290 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000 HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 360 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 7208 ETag: W/"1c28-jzMKoc+DPSvVfJwC7jYRDNnpaUs" set-cookie: connect.sid=s%3AQwLdXMcnkQaq6YvZvtTYL4BnMHb9eAv4.NEqu3dKtNsc%2F4nMbEdjeASDgie%2Bfj1FBoAOQDFNalTo; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 7,208 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="OWASP NodeGoat Project: Insecure App"> <meta name="version" content="v1.2"> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="https://www.owasp.org/index.php/Projects/OWASP_Node_js_Goat_Project">OWASP Node Goat Project</a> </div> <!-- Nav Links--> <div class="collapse navbar-collapse navbar-ex1-collapse"> <!-- top nav --> <ul class="nav navbar-nav navbar-right navbar-user"> <li class="dropdown user-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" style="font-size: larger"><i class="fa fa-info-circle"></i></a> <ul class="dropdown-menu alert-dropdown" style="min-width: 350px; padding: 10px"> <li> <p> The OWASP Node Goat is an educational Node.js web application vulnerable to the <a target="_blank" href="https://www.owasp.org/index.php/Top_10_2013-Top_10"> OWASP Top 10</a> risks.</p> <p>It is intended to show how each of these vulnerabilities can manifest in a Node.js specific way, and provides the subsequent mitigation for each with source code examples. </p> <p>To start hacking the application, login using the form below, or access the tutorial guide to know more.</p> </li> <li class="divider"></li> <li style="text-align: right"> <i class="fa fa-tag"> </i> v1.2 </li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div style="text-align: center; padding: 30px"> <img src="/images/owasplogo.png" height="80px"> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-4"></div> <div class="col-lg-4"> <div class="panel panel-info"> <div class="panel-heading" style="text-align: center"> <a href="/tutorial" target="_blank"> <b><span class="fa fa-book"></span> Tutorial Guide:</b> Learn OWASP Top 10 </a> </div> </div> <div class="panel panel-default"> <div class="panel-heading" style="text-align: center"> <span style="font-size: x-large"> <span class="fa fa-bullseye"></span>Retire<b>Easy</b> </span> <br /> <span style="font-size: medium">Employee Retirement Savings Management</span> <br /> <br /> </div> <div class="panel-body"> <form method="post" role="form" method="post" id="loginform"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" name="userName" value="" placeholder="Enter User Name"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter Password"> </div> <input type="hidden" name="_csrf" value="" /> <div class="row"> <div class="col-lg-4"><a href="/signup">New user? Sign Up</a> </div> <div class="col-lg-5"></div> <div class="col-lg-3"> <button type="submit" class="btn btn-danger">Submit</button> </div> </div> </form> </div> </div> </div> <div class="col-lg-4"></div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> <!-- /.row --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> <script type="application/javascript"> const areCookiesEnabled = () => { const cookieEnabled = navigator.cookieEnabled; // When cookieEnabled flag is present and false then cookies are disabled. if (!cookieEnabled) return false; // try to set a test cookie if we can't see any cookies and we're using // either a browser that doesn't support navigator.cookieEnabled // or IE (which always returns true for navigator.cookieEnabled) if (!document.cookie && cookieEnabled === null) { document.cookie = "testcookie=1"; if (!document.cookie) return false; document.cookie = "testcookie=; expires=" + new Date(0).toUTCString(); } return true; } $(document).ready(() => { if (!areCookiesEnabled()) { $("#page-wrapper").prepend("<div class=\"row\"><div class=\"col-lg-12\"><div class=\"alert alert-danger\">Cookies are not enabled on your browser. Please enable cookies in your browser preferences to continue.</div></div></div>"); } }); </script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/login |
| Method | GET |
| Parameter | http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js |
| Attack | |
| Evidence | <script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> |
| Request Header - size: 498 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/login HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 7208 ETag: W/"1c28-jzMKoc+DPSvVfJwC7jYRDNnpaUs" Date: Mon, 29 Jan 2024 16:33:31 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 7,208 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="OWASP NodeGoat Project: Insecure App"> <meta name="version" content="v1.2"> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="https://www.owasp.org/index.php/Projects/OWASP_Node_js_Goat_Project">OWASP Node Goat Project</a> </div> <!-- Nav Links--> <div class="collapse navbar-collapse navbar-ex1-collapse"> <!-- top nav --> <ul class="nav navbar-nav navbar-right navbar-user"> <li class="dropdown user-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" style="font-size: larger"><i class="fa fa-info-circle"></i></a> <ul class="dropdown-menu alert-dropdown" style="min-width: 350px; padding: 10px"> <li> <p> The OWASP Node Goat is an educational Node.js web application vulnerable to the <a target="_blank" href="https://www.owasp.org/index.php/Top_10_2013-Top_10"> OWASP Top 10</a> risks.</p> <p>It is intended to show how each of these vulnerabilities can manifest in a Node.js specific way, and provides the subsequent mitigation for each with source code examples. </p> <p>To start hacking the application, login using the form below, or access the tutorial guide to know more.</p> </li> <li class="divider"></li> <li style="text-align: right"> <i class="fa fa-tag"> </i> v1.2 </li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div style="text-align: center; padding: 30px"> <img src="/images/owasplogo.png" height="80px"> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-4"></div> <div class="col-lg-4"> <div class="panel panel-info"> <div class="panel-heading" style="text-align: center"> <a href="/tutorial" target="_blank"> <b><span class="fa fa-book"></span> Tutorial Guide:</b> Learn OWASP Top 10 </a> </div> </div> <div class="panel panel-default"> <div class="panel-heading" style="text-align: center"> <span style="font-size: x-large"> <span class="fa fa-bullseye"></span>Retire<b>Easy</b> </span> <br /> <span style="font-size: medium">Employee Retirement Savings Management</span> <br /> <br /> </div> <div class="panel-body"> <form method="post" role="form" method="post" id="loginform"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" name="userName" value="" placeholder="Enter User Name"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter Password"> </div> <input type="hidden" name="_csrf" value="" /> <div class="row"> <div class="col-lg-4"><a href="/signup">New user? Sign Up</a> </div> <div class="col-lg-5"></div> <div class="col-lg-3"> <button type="submit" class="btn btn-danger">Submit</button> </div> </div> </form> </div> </div> </div> <div class="col-lg-4"></div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> <!-- /.row --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> <script type="application/javascript"> const areCookiesEnabled = () => { const cookieEnabled = navigator.cookieEnabled; // When cookieEnabled flag is present and false then cookies are disabled. if (!cookieEnabled) return false; // try to set a test cookie if we can't see any cookies and we're using // either a browser that doesn't support navigator.cookieEnabled // or IE (which always returns true for navigator.cookieEnabled) if (!document.cookie && cookieEnabled === null) { document.cookie = "testcookie=1"; if (!document.cookie) return false; document.cookie = "testcookie=; expires=" + new Date(0).toUTCString(); } return true; } $(document).ready(() => { if (!areCookiesEnabled()) { $("#page-wrapper").prepend("<div class=\"row\"><div class=\"col-lg-12\"><div class=\"alert alert-danger\">Cookies are not enabled on your browser. Please enable cookies in your browser preferences to continue.</div></div></div>"); } }); </script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/signup |
| Method | GET |
| Parameter | http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js |
| Attack | |
| Evidence | <script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> |
| Request Header - size: 570 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/signup HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Connection: keep-alive Cookie: connect.sid=s%3AIF9C8qOuAKIcRfBbQqlCJJXkbklBl-qx.oP%2BOVOd6OEM180NJJ02GnInP0AWbC%2BM6FRljTBVrJ0U Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 4551 ETag: W/"11c7-Y/9Bw9cdVN5/8qERn0VzdrK/7QY" Date: Mon, 29 Jan 2024 16:33:44 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 4,551 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <!-- Add custom CSS here --> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="/">OWASP Node Goat Project</a> </div> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div class="well well-sm"> Already a user? <a href="/login">Login</a> <p> </div> </div> </div> <!-- /.row --> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Enter sign up information</h3> </div> <div class="panel-body"> <form method="post" role="form" method="post"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" value="" name="userName" placeholder="Enter user name"> </div> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" value="" name="firstName" placeholder="Enter first name"> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" value="" name="lastName" placeholder="Enter last name"> </div> <div class="form-group"> <label for="lastname">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Verify Password</label> <input type="password" class="form-control" id="verify" name="verify" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Email (Optional)</label> <input type="email" class="form-control" id="email" name="email" value="" placeholder="Enter email"> </div> <input type="hidden" name="_csrf" value=""></input> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/tutorial |
| Method | GET |
| Parameter | http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js |
| Attack | |
| Evidence | <script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> |
| Request Header - size: 570 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/tutorial HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 233 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 27010 ETag: W/"6982-Li2JuR00Z8ulcGovuWWgt5WzEqM" Date: Mon, 29 Jan 2024 16:33:43 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 27,010 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>Tutorial - OWASP Node Goat Project</title> <!-- Bootstrap core CSS --> <link href="../vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Add custom CSS here --> <link href="../vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="../vendor/theme/font-awesome/css/font-awesome.min.css"> <!--[if lt IE 9]><script src="../vendor/html5shiv.js"><![endif]--> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/tutorial"><b>OWASP Node Goat Tutorial:</b> Fixing OWASP Top 10 </a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse navbar-ex1-collapse"> <ul class="nav navbar-nav side-nav"> <li><a href="/tutorial/a1"><i class="fa fa-wrench"></i> A1 Injection</a> </li> <li><a href="/tutorial/a2"><i class="fa fa-wrench"></i> A2 Broken Auth</a> </li> <li><a href="/tutorial/a3"><i class="fa fa-wrench"></i> A3 XSS</a> </li> <li><a href="/tutorial/a4"><i class="fa fa-wrench"></i> A4 Insecure DOR</a> </li> <li><a href="/tutorial/a5"><i class="fa fa-wrench"></i> A5 Misconfig</a> </li> <li><a href="/tutorial/a6"><i class="fa fa-wrench"></i> A6 Sensitive Data</a> </li> <li><a href="/tutorial/a7"><i class="fa fa-wrench"></i> A7 Access Controls</a> </li> <li><a href="/tutorial/a8"><i class="fa fa-wrench"></i> A8 CSRF</a> </li> <li><a href="/tutorial/a9"><i class="fa fa-wrench"></i> A9 Insecure Components</a> </li> <li><a href="/tutorial/a10"><i class="fa fa-wrench"></i> A10 Redirects</a> </li> <li><a href="/tutorial/redos"><i class="fa"></i> ReDoS Attacks</a> </li> <li><a href="/tutorial/ssrf"><i class="fa"></i> SSRF</a> </li> </ul> <ul class="nav navbar-nav navbar-right navbar-user"> <li><a href="/login"><i class="fa fa-power-off"></i> Exit</a> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <h1>A1 - Injection <small></small> </h1> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="bs-example" style="margin-bottom: 40px;"> <span class="label label-danger">Exploitability: EASY</span> <span class="label label-warning">Prevalence: COMMON</span> <span class="label label-warning">Detectability: AVERAGE</span> <span class="label label-danger">Technical Impact: SEVERE</span> </div> </div> </div> <div class="row"> <div class="col-lg-12"> <div class="panel panel-info"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> Injection flaws occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization. </div> </div> <!-- <div class="panel panel-info"> <div class="panel-heading"> <h3 class="panel-title">Real World Attack Incident Examples</h3> </div> <div class="panel-body"> Screencast here ... </div> </div> --> </div> </div> <!-- accordions --> <div class="panel-group" id="accordion"> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne"> <i class="fa fa-chevron-down"></i>A1 - 1 Server Side JS Injection </a> </h4> </div> <div id="collapseOne" class="panel-collapse collapse in"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> When <code>eval()</code>, <code>setTimeout()</code>, <code>setInterval()</code>, <code>Function()</code>are used to process user provided inputs, it can be exploited by an attacker to inject and execute malicious JavaScript code on server. </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p> Web applications using the JavaScript <code>eval()</code>function to parse the incoming data without any type of input validation are vulnerable to this attack. An attacker can inject arbitrary JavaScript code to be executed on the server. Similarly <code>setTimeout()</code>, and <code>setInterval()</code>functions can take code in string format as a first argument causing same issues as <code>eval()</code>. </p> <p>This vulnerability can be very critical and damaging by allowing attacker to send various types of commands.</p> <p> <b>Denial of Service Attack:</b> </p> <iframe width="560" height="315" src="//www.youtube.com/embed/krOx9QWwcYw?rel=0" frameborder="0" allowfullscreen></iframe> <p> An effective denial-of-service attack can be executed simply by sending the commands below to <code>eval()</code>function: </p> <pre>while(1)</pre> <p> This input will cause the target server's event loop to use 100% of its processor time and unable to process any other incoming requests until process is restarted. </p> <p> An alternative DoS attack would be to simply exit or kill the running process: <pre>process.exit()</pre> or <pre>process.kill(process.pid) </pre> </p> <p> <b>File System Access</b> <br/> </p> <iframe width="560" height="315" src="//www.youtube.com/embed/Mr-Jh9bjSLo?rel=0" frameborder="0" allowfullscreen></iframe> <p> Another potential goal of an attacker might be to read the contents of files from the server. For example, following two commands list the contents of the current directory and parent directory respectively: </p> <p> <pre>res.end(require('fs').readdirSync('.').toString())</pre> <pre>res.end(require('fs').readdirSync('..').toString()) </pre> </p> <p> Once file names are obtained, an attacker can issue the command below to view the actual contents of a file: </p> <p> <pre>res.end(require('fs').readFileSync(filename))</pre> </p> <p> An attacker can further exploit this vulnerability by writing and executing harmful binary files using <code>fs</code>and <code>child_process</code>modules. </p> </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> To prevent server-side js injection attacks: <ul> <li>Validate user inputs on server side before processing</li> <li>Do not use <code>eval()</code>function to parse user inputs. Avoid using other commands with similar effect, such as <code>setTimeOut()</code>, <code>setInterval()</code>, and <code>Function()</code>. </li> <li> For parsing JSON input, instead of using <code>eval()</code>, use a safer alternative such as <code>JSON.parse()</code>. For type conversions use type related <code>parseXXX()</code>methods. </li> <li>Include <code>"use strict"</code>at the beginning of a function, which enables <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode"> strict mode </a>within the enclosing function scope.</li> </ul> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p>In <code>routes/contributions.js</code>, the <code>handleContributionsUpdate()</code>function insecurely uses <code>eval()</code>to convert user supplied contribution amounts to integer. <pre> // Insecure use of eval() to parse inputs var preTax = eval(req.body.preTax); var afterTax = eval(req.body.afterTax); var roth = eval(req.body.roth); </pre> This makes application vulnerable to SSJS attack. It can fixed simply by using <code>parseInt()</code>instead. <pre> //Fix for A1 -1 SSJS Injection attacks - uses alternate method to eval var preTax = parseInt(req.body.preTax); var afterTax = parseInt(req.body.afterTax); var roth = parseInt(req.body.roth); </pre> </p> <p>In addition, all functions begin with <code>use strict</code>pragma. </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Further Reading</h3> </div> <div class="panel-body"> <ul> <li><a target="_blank" href="https://media.blackhat.com/bh-us-11/Sullivan/BH_US_11_Sullivan_Server_Side_WP.pdf">“ServerSide JavaScript Injection: Attacking NoSQL and Node.js"</a> a whitepaper by Bryan Sullivan.</li> </ul> </div> </div> </div> </div> </div> <!-- /ssjs --> <!-- DB Injection --> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo"> <i class="fa fa-chevron-down"></i> A1 - 2 SQL and NoSQL Injection </a> </h4> </div> <div id="collapseTwo" class="panel-collapse"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> <p> SQL and NoSQL injections enable an attacker to inject code into the query that would be executed by the database. These flaws are introduced when software developers create dynamic database queries that include user supplied input. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p>Both SQL and NoSQL databases are vulnerable to injection attack. Here is an example of equivalent attack in both cases, where attacker manages to retrieve admin user's record without knowing password:</p> <h5>1. SQL Injection</h5> <p>Lets consider an example SQL statement used to authenticate the user with username and password</p> <pre>SELECT * FROM accounts WHERE username = '$username' AND password = '$password'</pre> <p>If this statement is not prepared or properly handled when constructed, an attacker may be able to supply <code>admin' --</code>in the username field to access the admin user's account bypassing the condition that checks for the password. The resultant SQL query would looks like:</p> <pre>SELECT * FROM accounts WHERE username = 'admin' -- AND password = ''</pre> <br/> <h5>2. NoSQL Injection</h5> <p>The equivalent of above query for NoSQL MongoDB database is:</p> <pre>db.accounts.find({username: username, password: password});</pre> <p>While here we are no longer dealing with query language, an attacker can still achieve the same results as SQL injection by supplying JSON input object as below:</p> <pre> { "username": "admin", "password": {$gt: ""} } </pre> <p>In MongoDB, <code>$gt</code>selects those documents where the value of the field is greater than (i.e. >) the specified value. Thus above statement compares password in database with empty string for greatness, which returns <code>true</code>.</p> <p>The same results can be achieved using other comparison operator such as <code>$ne</code>.</p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">SSJS Attack Mechanics</h3> </div> <div class="panel-body"> <p> Server-side JavaScript Injection (SSJS) is an attack where JavaScript code is injected and executed in a server component. MongoDB specifically, is vulnerable to this attack when queries are run without proper sanitization. </p> <h5>$where operator</h5> <p> MongoDB's <code>$where</code> operator performs JavaScript expression evaluation on the MongoDB server. If the user is able to inject direct code into such queries then such an attack can take place </p> <p> Lets consider an example query: </p> <pre> db.allocationsCollection.find({ $where: "this.userId == '" + parsedUserId + "' && " + "this.stocks > " + "'" + threshold + "'" }); </pre> <p> The code will match all documents which have a <code>userId</code> field as specified by <code>parsedUserId</code> and a <code>stocks</code> field as specified by <code>threshold</code>. The problem is that these parameters are not validated, filtered, or sanitised, and vulnerable to SSJS Injection. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> Here are some measures to prevent SQL / NoSQL injection attacks, or minimize impact if it happens: <ul> <li>Prepared Statements: For SQL calls, use prepared statements instead of building dynamic queries using string concatenation.</li> <li>Input Validation: Validate inputs to detect malicious values. For NoSQL databases, also validate input types against expected types</li> <li>Least Privilege: To minimize the potential damage of a successful injection attack, do not assign DBA or admin type access rights to your application accounts. Similarly minimize the privileges of the operating system account that the database process runs under.</li> </ul> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p><strong>Note: These vulnerabilities are not present when using an Atlas M0 cluster with NodeGoat.</strong></p> <p>The Allocations page of the demo application is vulnerable to NoSQL Injection. For example, set the stocks threshold filter to:</p> <pre>1'; return 1 == '1</pre> <p>This will retrieve allocations for all the users in the database.</p> <p>An attacker could also send the following input for the <code>threshold</code> field in the request's query, which will create a valid JavaScript expression and satisfy the <code> $where</code> query as well, resulting in a DoS attack on the MongoDB server: </p> <pre>http://localhost:4000/allocations/2?threshold=5';while(true){};' </pre> <p> You can also just drop the following into the Stocks Threshold input box: </p> <pre>';while(true){};'</pre> <p>For these vulnerabilities, bare minimum fixes can be found in <code>allocations.html</code> and <code>allocations-dao.js</code></p> </div> </div> </div> </div> </div> <!-- /NoSQL Injection --> <!-- Log Injection --> <div class="panel panel-info"> <div class="panel-heading"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree"> <i class="fa fa-chevron-down"></i> A1 - 3 Log Injection </a> </h4> </div> <div id="collapseThree" class="panel-collapse"> <div class="panel-body"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> <p> Log injection vulnerabilities enable an attacker to forge and tamper with an application's logs. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Attack Mechanics</h3> </div> <div class="panel-body"> <p>An attacker may craft a malicious request that may deliberately fail, which the application will log, and when attacker's user input is unsanitized, the payload is sent as-is to the logging facility. Vulnerabilities may vary depending on the logging facility:</p> <h5>1. Log Forging (CRLF) </h5> <p>Lets consider an example where an application logs a failed attempt to login to the system. A very common example for this is as follows: </p> <pre> var userName = req.body.userName; console.log('Error: attempt to login with invalid user: ', userName); </pre> <p>When user input is unsanitized and the output mechanism is an ordinary terminal stdout facility then the application will be vulnerable to CRLF injection, where an attacker can create a malicious payload as follows: <pre> curl http://localhost:4000/login -X POST --data 'userName=vyva%0aError: alex moldovan failed $1,000,000 transaction&password=Admin_123&_csrf=' </pre> Where the <code>userName</code> parameter is encoding in the request the LF symbol which will result in a new line to begin. Resulting log output will look as follows: <pre> Error: attempt to login with invalid user: vyva Error: alex moldovan failed $1,000,000 transaction </pre> <br/> <h5>2. Log Injection Escalation </h5> <p> An attacker may craft malicious input in hope of an escalated attack where the target isn't the logs themselves, but rather the actual logging system. For example, if an application has a back-office web app that manages viewing and tracking the logs, then an attacker may send an XSS payload into the log, which may not result in log forging on the log itself, but when viewed by a system administrator on the log viewing web app then it may compromise it and result in XSS injection that if the logs app is vulnerable. </p> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">How Do I Prevent It?</h3> </div> <div class="panel-body"> As always when dealing with user input: <ul> <li> Do not allow user input into logs </li> <li> Encode to proper context, or sanitize user input </li> </ul> Encoding example: <pre> // Step 1: Require a module that supports encoding var ESAPI = require('node-esapi'); // - Step 2: Encode the user input that will be logged in the correct context // following are a few examples: console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForHTML(userName)); console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForJavaScript(userName)); console.log('Error: attempt to login with invalid user: %s', ESAPI.encoder().encodeForURL(userName)); </pre> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Source Code Example</h3> </div> <div class="panel-body"> <p>For the above Log Injection vulnerability, example and fix can be found at <code>routes/session.js</code></p> </div> </div> </div> </div> </div> <!-- /Log Injection --> </div> <!-- end accordions --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <script src="../vendor/jquery.min.js"></script> <script src="../vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/login |
| Method | POST |
| Parameter | http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js |
| Attack | |
| Evidence | <script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> |
| Request Header - size: 697 bytes. |
POST http://jenkins_docker-compose_application_web_1:4000/login HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Content-Type: application/x-www-form-urlencoded Content-Length: 34 Origin: http://jenkins_docker-compose_application_web_1:4000 Connection: keep-alive Cookie: connect.sid=s%3AyGMSRGNYEF-6z61RLvRrrBNTAh_dtQGn.53w2hKRBLZfOMBxxohiuNfCoghCrZtv7qOJEujRc5IM Upgrade-Insecure-Requests: 1 |
| Request Body - size: 34 bytes. |
userName=HhyVAgNS&password=&_csrf=
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 7514 ETag: W/"1d5a-vBvXIMawvps2XiuMx1Ih4luZS3I" Date: Mon, 29 Jan 2024 16:33:48 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 7,514 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="OWASP NodeGoat Project: Insecure App"> <meta name="version" content="v1.2"> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="https://www.owasp.org/index.php/Projects/OWASP_Node_js_Goat_Project">OWASP Node Goat Project</a> </div> <!-- Nav Links--> <div class="collapse navbar-collapse navbar-ex1-collapse"> <!-- top nav --> <ul class="nav navbar-nav navbar-right navbar-user"> <li class="dropdown user-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" style="font-size: larger"><i class="fa fa-info-circle"></i></a> <ul class="dropdown-menu alert-dropdown" style="min-width: 350px; padding: 10px"> <li> <p> The OWASP Node Goat is an educational Node.js web application vulnerable to the <a target="_blank" href="https://www.owasp.org/index.php/Top_10_2013-Top_10"> OWASP Top 10</a> risks.</p> <p>It is intended to show how each of these vulnerabilities can manifest in a Node.js specific way, and provides the subsequent mitigation for each with source code examples. </p> <p>To start hacking the application, login using the form below, or access the tutorial guide to know more.</p> </li> <li class="divider"></li> <li style="text-align: right"> <i class="fa fa-tag"> </i> v1.2 </li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div style="text-align: center; padding: 30px"> <img src="/images/owasplogo.png" height="80px"> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-4"></div> <div class="col-lg-4"> <div class="panel panel-info"> <div class="panel-heading" style="text-align: center"> <a href="/tutorial" target="_blank"> <b><span class="fa fa-book"></span> Tutorial Guide:</b> Learn OWASP Top 10 </a> </div> </div> <div class="panel panel-default"> <div class="panel-heading" style="text-align: center"> <span style="font-size: x-large"> <span class="fa fa-bullseye"></span>Retire<b>Easy</b> </span> <br /> <span style="font-size: medium">Employee Retirement Savings Management</span> <br /> <br /> </div> <div class="panel-body"> <div class="alert alert-dismissable alert-danger"> <button type="button" class="close" data-dismiss="alert">×</button> Invalid username </div> <form method="post" role="form" method="post" id="loginform"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" name="userName" value="HhyVAgNS" placeholder="Enter User Name"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter Password"> </div> <input type="hidden" name="_csrf" value="" /> <div class="row"> <div class="col-lg-4"><a href="/signup">New user? Sign Up</a> </div> <div class="col-lg-5"></div> <div class="col-lg-3"> <button type="submit" class="btn btn-danger">Submit</button> </div> </div> </form> </div> </div> </div> <div class="col-lg-4"></div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> <!-- /.row --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> <script type="application/javascript"> const areCookiesEnabled = () => { const cookieEnabled = navigator.cookieEnabled; // When cookieEnabled flag is present and false then cookies are disabled. if (!cookieEnabled) return false; // try to set a test cookie if we can't see any cookies and we're using // either a browser that doesn't support navigator.cookieEnabled // or IE (which always returns true for navigator.cookieEnabled) if (!document.cookie && cookieEnabled === null) { document.cookie = "testcookie=1"; if (!document.cookie) return false; document.cookie = "testcookie=; expires=" + new Date(0).toUTCString(); } return true; } $(document).ready(() => { if (!areCookiesEnabled()) { $("#page-wrapper").prepend("<div class=\"row\"><div class=\"col-lg-12\"><div class=\"alert alert-danger\">Cookies are not enabled on your browser. Please enable cookies in your browser preferences to continue.</div></div></div>"); } }); </script> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/signup |
| Method | POST |
| Parameter | http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js |
| Attack | |
| Evidence | <script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> |
| Request Header - size: 701 bytes. |
POST http://jenkins_docker-compose_application_web_1:4000/signup HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/signup Content-Type: application/x-www-form-urlencoded Content-Length: 86 Origin: http://jenkins_docker-compose_application_web_1:4000 Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg Upgrade-Insecure-Requests: 1 |
| Request Body - size: 86 bytes. |
userName=ECeNuwfl&firstName=zAuRhWJS&lastName=GuQMUShW&password=&verify=&email=&_csrf=
|
| Response Header - size: 232 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 4999 ETag: W/"1387-k/xYlSuNY0T8Jt7I4fy0VJVIBXA" Date: Mon, 29 Jan 2024 16:33:58 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 4,999 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <title>OWASP Node Goat</title> <!-- Bootstrap core CSS --> <link href="vendor/bootstrap/bootstrap.css" rel="stylesheet"> <!-- Theme CSS --> <link href="vendor/theme/sb-admin.css" rel="stylesheet"> <link rel="stylesheet" href="vendor/theme/font-awesome/css/font-awesome.min.css"> <!-- Add custom CSS here --> <style type="text/css"> #wrapper { padding-left: 0; } </style> </head> <body> <div id="wrapper"> <!-- Sidebar --> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <a class="navbar-brand" href="/">OWASP Node Goat Project</a> </div> </nav> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <div class="well well-sm"> Already a user? <a href="/login">Login</a> <p> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="alert alert-dismissable alert-danger"> <button type="button" class="close" data-dismiss="alert">×</button> <p>Password must be 8 to 18 characters including numbers, lowercase and uppercase letters.</p> </div> </div> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Enter sign up information</h3> </div> <div class="panel-body"> <form method="post" role="form" method="post"> <div class="form-group"> <label for="userName">User Name</label> <input type="text" class="form-control" id="userName" value="ECeNuwfl" name="userName" placeholder="Enter user name"> </div> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" value="" name="firstName" placeholder="Enter first name"> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" value="" name="lastName" placeholder="Enter last name"> </div> <div class="form-group"> <label for="lastname">Password</label> <input type="password" class="form-control" id="password" name="password" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Verify Password</label> <input type="password" class="form-control" id="verify" name="verify" value="" placeholder="Enter password"> </div> <div class="form-group"> <label for="verify">Email (Optional)</label> <input type="email" class="form-control" id="email" name="email" value="" placeholder="Enter email"> </div> <input type="hidden" name="_csrf" value=""></input> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <!-- Bootstrap core JavaScript --> <script src="/vendor/jquery.min.js"></script> <script src="/vendor/bootstrap/bootstrap.js"></script> <!-- Load environmental scripts such as live reload --> <script>document.write("<script src='http://" + (location.host || "localhost").split(":")[0] + ":35729/livereload.js'></" + "script>");</script> </body> </html> |
| Instances | 6 |
| Solution |
Ensure JavaScript source files are loaded from only trusted sources, and the sources can't be controlled by end users of the application.
|
| Reference | |
| Tags | OWASP_2021_A08 |
| CWE Id | 829 |
| WASC Id | 15 |
| Plugin Id | 10017 |
|
Low |
Server Leaks Information via "X-Powered-By" HTTP Response Header Field(s) |
|---|---|
| Description |
The web/application server is leaking information via one or more "X-Powered-By" HTTP response headers. Access to such information may facilitate attackers identifying other frameworks/components your web application is reliant upon and the vulnerabilities such components may be subject to.
|
| URL | http://jenkins_docker-compose_application_web_1:4000 |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | X-Powered-By: Express |
| Request Header - size: 179 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000 HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 348 bytes. |
HTTP/1.1 302 Found
X-Powered-By: Express Location: /login Vary: Accept Content-Type: text/plain; charset=utf-8 Content-Length: 28 set-cookie: connect.sid=s%3A2AoTPOmAOJtx2rXevPFTWfOgR8YGCZcc.bdYKd173c5UXsZzxlkfnIp%2FopQMrKHCQ2m3ggq7R2I8; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 28 bytes. |
Found. Redirecting to /login
|
| URL | http://jenkins_docker-compose_application_web_1:4000/ |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | X-Powered-By: Express |
| Request Header - size: 389 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/ HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive Upgrade-Insecure-Requests: 1 |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 347 bytes. |
HTTP/1.1 302 Found
X-Powered-By: Express Location: /login Vary: Accept Content-Type: text/html; charset=utf-8 Content-Length: 56 set-cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:31 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 56 bytes. |
<p>Found. Redirecting to <a href="/login">/login</a></p>
|
| URL | http://jenkins_docker-compose_application_web_1:4000/.git/index |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | X-Powered-By: Express |
| Request Header - size: 190 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/.git/index HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 149 set-cookie: connect.sid=s%3AwqnsNnm0JNFr_c-ILLR7CjdG_uYo4VVW.cytWnLVcvPGOUZGePLI29wnKDcy1OW5%2B892M9AdtZFA; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 149 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /.git/index</pre> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/.svn/entries |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | X-Powered-By: Express |
| Request Header - size: 192 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/.svn/entries HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 151 set-cookie: connect.sid=s%3AjqDNMm6bCo9hIi4k-zSL1pEgKROsV3T2.QSVBq3yrtKUDHQC9%2FBsCW1JAc24P7RopxS7EnSiFTqA; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 151 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /.svn/entries</pre> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/.svn/wc.db |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | X-Powered-By: Express |
| Request Header - size: 190 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/.svn/wc.db HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 user-agent: pragma: no-cache cache-control: no-cache |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 398 bytes. |
HTTP/1.1 404 Not Found
X-Powered-By: Express Content-Security-Policy: default-src 'self' X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8 Content-Length: 149 set-cookie: connect.sid=s%3Asv3hkzV3_ZpgbbMGSiyiA7G3ZgnCwyMt.hhEWpjJazSBDCxwMLxvQhhRLtPw%2Fsa2BSVPotWkO4KU; Path=/; HttpOnly Date: Mon, 29 Jan 2024 16:33:24 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 149 bytes. |
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /.svn/wc.db</pre> </body> </html> |
| URL | http://jenkins_docker-compose_application_web_1:4000/favicon.ico |
| Method | GET |
| Parameter | |
| Attack | |
| Evidence | X-Powered-By: Express |
| Request Header - size: 483 bytes. |
GET http://jenkins_docker-compose_application_web_1:4000/favicon.ico HTTP/1.1
host: jenkins_docker-compose_application_web_1:4000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: image/avif,image/webp,*/* Accept-Language: en-US,en;q=0.5 Referer: http://jenkins_docker-compose_application_web_1:4000/login Connection: keep-alive Cookie: connect.sid=s%3AXy8T7SjD3MErMkzTfsj-5hNbVCLbZz9B.3xiSWrm7kN659RPaOpzNgStJEQfhKbBaE%2BXXCtk4BVg |
| Request Body - size: 0 bytes. |
|
| Response Header - size: 262 bytes. |
HTTP/1.1 200 OK
X-Powered-By: Express Cache-Control: public, max-age=31536000 ETag: "51a06-zKhF24g/pW1Cvky7McwSt/aOdFM" Content-Length: 334342 Content-Type: image/x-icon Date: Mon, 29 Jan 2024 16:33:32 GMT Connection: keep-alive Keep-Alive: timeout=5 |
| Response Body - size: 334,342 bytes. |
ý È & |